Annotation of embedaddon/php/ext/mbstring/mbstring.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | PHP Version 5                                                        |
                      4:    +----------------------------------------------------------------------+
1.1.1.3 ! misho       5:    | Copyright (c) 1997-2013 The PHP Group                                |
1.1       misho       6:    +----------------------------------------------------------------------+
                      7:    | This source file is subject to version 3.01 of the PHP license,      |
                      8:    | that is bundled with this package in the file LICENSE, and is        |
                      9:    | available through the world-wide-web at the following url:           |
                     10:    | http://www.php.net/license/3_01.txt                                  |
                     11:    | If you did not receive a copy of the PHP license and are unable to   |
                     12:    | obtain it through the world-wide-web, please send a note to          |
                     13:    | license@php.net so we can mail you a copy immediately.               |
                     14:    +----------------------------------------------------------------------+
                     15:    | Author: Tsukada Takuya <tsukada@fminn.nagano.nagano.jp>              |
                     16:    |         Rui Hirokawa <hirokawa@php.net>                              |
                     17:    +----------------------------------------------------------------------+
                     18:  */
                     19: 
1.1.1.2   misho      20: /* $Id$ */
1.1       misho      21: 
                     22: /*
                     23:  * PHP 4 Multibyte String module "mbstring"
                     24:  *
                     25:  * History:
                     26:  *   2000.5.19  Release php-4.0RC2_jstring-1.0
                     27:  *   2001.4.1   Release php4_jstring-1.0.91
                     28:  *   2001.4.30  Release php4_jstring-1.1 (contribute to The PHP Group)
                     29:  *   2001.5.1   Renamed from jstring to mbstring (hirokawa@php.net)
                     30:  */
                     31: 
                     32: /*
                     33:  * PHP3 Internationalization support program.
                     34:  *
                     35:  * Copyright (c) 1999,2000 by the PHP3 internationalization team.
                     36:  * All rights reserved.
                     37:  *
                     38:  * See README_PHP3-i18n-ja for more detail.
                     39:  *
                     40:  * Authors:
                     41:  *    Hironori Sato <satoh@jpnnet.com>
                     42:  *    Shigeru Kanemoto <sgk@happysize.co.jp>
                     43:  *    Tsukada Takuya <tsukada@fminn.nagano.nagano.jp>
                     44:  *    Rui Hirokawa <rui_hirokawa@ybb.ne.jp>
                     45:  */
                     46: 
                     47: /* {{{ includes */
                     48: #ifdef HAVE_CONFIG_H
                     49: #include "config.h"
                     50: #endif
                     51: 
                     52: #include "php.h"
                     53: #include "php_ini.h"
                     54: #include "php_variables.h"
                     55: #include "mbstring.h"
                     56: #include "ext/standard/php_string.h"
                     57: #include "ext/standard/php_mail.h"
                     58: #include "ext/standard/exec.h"
                     59: #include "ext/standard/php_smart_str.h"
                     60: #include "ext/standard/url.h"
                     61: #include "main/php_output.h"
                     62: #include "ext/standard/info.h"
                     63: 
                     64: #include "libmbfl/mbfl/mbfl_allocators.h"
1.1.1.2   misho      65: #include "libmbfl/mbfl/mbfilter_pass.h"
1.1       misho      66: 
                     67: #include "php_variables.h"
                     68: #include "php_globals.h"
                     69: #include "rfc1867.h"
                     70: #include "php_content_types.h"
                     71: #include "SAPI.h"
                     72: #include "php_unicode.h"
                     73: #include "TSRM.h"
                     74: 
                     75: #include "mb_gpc.h"
                     76: 
                     77: #if HAVE_MBREGEX
                     78: #include "php_mbregex.h"
                     79: #endif
                     80: 
                     81: #include "zend_multibyte.h"
                     82: 
                     83: #if HAVE_ONIG
                     84: #include "php_onig_compat.h"
                     85: #include <oniguruma.h>
                     86: #undef UChar
                     87: #elif HAVE_PCRE || HAVE_BUNDLED_PCRE
                     88: #include "ext/pcre/php_pcre.h"
                     89: #endif
                     90: /* }}} */
                     91: 
                     92: #if HAVE_MBSTRING
                     93: 
                     94: /* {{{ prototypes */
                     95: ZEND_DECLARE_MODULE_GLOBALS(mbstring)
                     96: 
                     97: static PHP_GINIT_FUNCTION(mbstring);
                     98: static PHP_GSHUTDOWN_FUNCTION(mbstring);
                     99: 
1.1.1.2   misho     100: static void php_mb_populate_current_detect_order_list(TSRMLS_D);
                    101: 
                    102: static int php_mb_encoding_translation(TSRMLS_D);
                    103: 
                    104: static void php_mb_gpc_get_detect_order(const zend_encoding ***list, size_t *list_size TSRMLS_DC);
                    105: 
                    106: static void php_mb_gpc_set_input_encoding(const zend_encoding *encoding TSRMLS_DC);
                    107: 
1.1       misho     108: /* }}} */
                    109: 
                    110: /* {{{ php_mb_default_identify_list */
                    111: typedef struct _php_mb_nls_ident_list {
                    112:        enum mbfl_no_language lang;
1.1.1.2   misho     113:        const enum mbfl_no_encoding *list;
                    114:        size_t list_size;
1.1       misho     115: } php_mb_nls_ident_list;
                    116: 
                    117: static const enum mbfl_no_encoding php_mb_default_identify_list_ja[] = {
                    118:        mbfl_no_encoding_ascii,
                    119:        mbfl_no_encoding_jis,
                    120:        mbfl_no_encoding_utf8,
                    121:        mbfl_no_encoding_euc_jp,
                    122:        mbfl_no_encoding_sjis
                    123: };
                    124: 
                    125: static const enum mbfl_no_encoding php_mb_default_identify_list_cn[] = {
                    126:        mbfl_no_encoding_ascii,
                    127:        mbfl_no_encoding_utf8,
                    128:        mbfl_no_encoding_euc_cn,
                    129:        mbfl_no_encoding_cp936
                    130: };
                    131: 
                    132: static const enum mbfl_no_encoding php_mb_default_identify_list_tw_hk[] = {
                    133:        mbfl_no_encoding_ascii,
                    134:        mbfl_no_encoding_utf8,
                    135:        mbfl_no_encoding_euc_tw,
                    136:        mbfl_no_encoding_big5
                    137: };
                    138: 
                    139: static const enum mbfl_no_encoding php_mb_default_identify_list_kr[] = {
                    140:        mbfl_no_encoding_ascii,
                    141:        mbfl_no_encoding_utf8,
                    142:        mbfl_no_encoding_euc_kr,
                    143:        mbfl_no_encoding_uhc
                    144: };
                    145: 
                    146: static const enum mbfl_no_encoding php_mb_default_identify_list_ru[] = {
                    147:        mbfl_no_encoding_ascii,
                    148:        mbfl_no_encoding_utf8,
                    149:        mbfl_no_encoding_koi8r,
                    150:        mbfl_no_encoding_cp1251,
                    151:        mbfl_no_encoding_cp866
                    152: };
                    153: 
                    154: static const enum mbfl_no_encoding php_mb_default_identify_list_hy[] = {
                    155:        mbfl_no_encoding_ascii,
                    156:        mbfl_no_encoding_utf8,
                    157:        mbfl_no_encoding_armscii8
                    158: };
                    159: 
                    160: static const enum mbfl_no_encoding php_mb_default_identify_list_tr[] = {
                    161:        mbfl_no_encoding_ascii,
                    162:        mbfl_no_encoding_utf8,
                    163:        mbfl_no_encoding_cp1254,
                    164:        mbfl_no_encoding_8859_9
                    165: };
                    166: 
                    167: static const enum mbfl_no_encoding php_mb_default_identify_list_ua[] = {
                    168:        mbfl_no_encoding_ascii,
                    169:        mbfl_no_encoding_utf8,
                    170:        mbfl_no_encoding_koi8u
                    171: };
                    172: 
                    173: static const enum mbfl_no_encoding php_mb_default_identify_list_neut[] = {
                    174:        mbfl_no_encoding_ascii,
                    175:        mbfl_no_encoding_utf8
                    176: };
                    177: 
                    178: 
                    179: static const php_mb_nls_ident_list php_mb_default_identify_list[] = {
                    180:        { mbfl_no_language_japanese, php_mb_default_identify_list_ja, sizeof(php_mb_default_identify_list_ja) / sizeof(php_mb_default_identify_list_ja[0]) },
                    181:        { mbfl_no_language_korean, php_mb_default_identify_list_kr, sizeof(php_mb_default_identify_list_kr) / sizeof(php_mb_default_identify_list_kr[0]) },
                    182:        { mbfl_no_language_traditional_chinese, php_mb_default_identify_list_tw_hk, sizeof(php_mb_default_identify_list_tw_hk) / sizeof(php_mb_default_identify_list_tw_hk[0]) },
                    183:        { mbfl_no_language_simplified_chinese, php_mb_default_identify_list_cn, sizeof(php_mb_default_identify_list_cn) / sizeof(php_mb_default_identify_list_cn[0]) },
                    184:        { mbfl_no_language_russian, php_mb_default_identify_list_ru, sizeof(php_mb_default_identify_list_ru) / sizeof(php_mb_default_identify_list_ru[0]) },
                    185:        { mbfl_no_language_armenian, php_mb_default_identify_list_hy, sizeof(php_mb_default_identify_list_hy) / sizeof(php_mb_default_identify_list_hy[0]) },
                    186:        { mbfl_no_language_turkish, php_mb_default_identify_list_tr, sizeof(php_mb_default_identify_list_tr) / sizeof(php_mb_default_identify_list_tr[0]) },
                    187:        { mbfl_no_language_ukrainian, php_mb_default_identify_list_ua, sizeof(php_mb_default_identify_list_ua) / sizeof(php_mb_default_identify_list_ua[0]) },
                    188:        { mbfl_no_language_neutral, php_mb_default_identify_list_neut, sizeof(php_mb_default_identify_list_neut) / sizeof(php_mb_default_identify_list_neut[0]) }
                    189: };
                    190: 
                    191: /* }}} */
                    192: 
                    193: /* {{{ mb_overload_def mb_ovld[] */
                    194: static const struct mb_overload_def mb_ovld[] = {
                    195:        {MB_OVERLOAD_MAIL, "mail", "mb_send_mail", "mb_orig_mail"},
                    196:        {MB_OVERLOAD_STRING, "strlen", "mb_strlen", "mb_orig_strlen"},
                    197:        {MB_OVERLOAD_STRING, "strpos", "mb_strpos", "mb_orig_strpos"},
                    198:        {MB_OVERLOAD_STRING, "strrpos", "mb_strrpos", "mb_orig_strrpos"},
                    199:        {MB_OVERLOAD_STRING, "stripos", "mb_stripos", "mb_orig_stripos"},
                    200:        {MB_OVERLOAD_STRING, "strripos", "mb_strripos", "mb_orig_strripos"},
                    201:        {MB_OVERLOAD_STRING, "strstr", "mb_strstr", "mb_orig_strstr"},
                    202:        {MB_OVERLOAD_STRING, "strrchr", "mb_strrchr", "mb_orig_strrchr"},
                    203:        {MB_OVERLOAD_STRING, "stristr", "mb_stristr", "mb_orig_stristr"},
                    204:        {MB_OVERLOAD_STRING, "substr", "mb_substr", "mb_orig_substr"},
                    205:        {MB_OVERLOAD_STRING, "strtolower", "mb_strtolower", "mb_orig_strtolower"},
                    206:        {MB_OVERLOAD_STRING, "strtoupper", "mb_strtoupper", "mb_orig_strtoupper"},
                    207:        {MB_OVERLOAD_STRING, "substr_count", "mb_substr_count", "mb_orig_substr_count"},
                    208: #if HAVE_MBREGEX
                    209:        {MB_OVERLOAD_REGEX, "ereg", "mb_ereg", "mb_orig_ereg"},
                    210:        {MB_OVERLOAD_REGEX, "eregi", "mb_eregi", "mb_orig_eregi"},
                    211:        {MB_OVERLOAD_REGEX, "ereg_replace", "mb_ereg_replace", "mb_orig_ereg_replace"},
                    212:        {MB_OVERLOAD_REGEX, "eregi_replace", "mb_eregi_replace", "mb_orig_eregi_replace"},
                    213:        {MB_OVERLOAD_REGEX, "split", "mb_split", "mb_orig_split"},
                    214: #endif
                    215:        {0, NULL, NULL, NULL}
                    216: }; 
                    217: /* }}} */
                    218: 
                    219: /* {{{ arginfo */
                    220: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_language, 0, 0, 0)
                    221:        ZEND_ARG_INFO(0, language)
                    222: ZEND_END_ARG_INFO()
                    223: 
                    224: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_internal_encoding, 0, 0, 0)
                    225:        ZEND_ARG_INFO(0, encoding)
                    226: ZEND_END_ARG_INFO()
                    227: 
                    228: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_http_input, 0, 0, 0)
                    229:        ZEND_ARG_INFO(0, type)
                    230: ZEND_END_ARG_INFO()
                    231: 
                    232: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_http_output, 0, 0, 0)
                    233:        ZEND_ARG_INFO(0, encoding)
                    234: ZEND_END_ARG_INFO()
                    235: 
                    236: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_detect_order, 0, 0, 0)
                    237:        ZEND_ARG_INFO(0, encoding)
                    238: ZEND_END_ARG_INFO()
                    239: 
                    240: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_substitute_character, 0, 0, 0)
                    241:        ZEND_ARG_INFO(0, substchar)
                    242: ZEND_END_ARG_INFO()
                    243: 
                    244: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_preferred_mime_name, 0, 0, 1)
                    245:        ZEND_ARG_INFO(0, encoding)
                    246: ZEND_END_ARG_INFO()
                    247: 
                    248: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_parse_str, 0, 0, 1)
                    249:        ZEND_ARG_INFO(0, encoded_string)
                    250:        ZEND_ARG_INFO(1, result)
                    251: ZEND_END_ARG_INFO()
                    252: 
                    253: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_output_handler, 0, 0, 2)
                    254:        ZEND_ARG_INFO(0, contents)
                    255:        ZEND_ARG_INFO(0, status)
                    256: ZEND_END_ARG_INFO()
                    257: 
                    258: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_strlen, 0, 0, 1)
                    259:        ZEND_ARG_INFO(0, str)
                    260:        ZEND_ARG_INFO(0, encoding)
                    261: ZEND_END_ARG_INFO()
                    262: 
                    263: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_strpos, 0, 0, 2)
                    264:        ZEND_ARG_INFO(0, haystack)
                    265:        ZEND_ARG_INFO(0, needle)
                    266:        ZEND_ARG_INFO(0, offset)
                    267:        ZEND_ARG_INFO(0, encoding)
                    268: ZEND_END_ARG_INFO()
                    269: 
                    270: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_strrpos, 0, 0, 2)
                    271:        ZEND_ARG_INFO(0, haystack)
                    272:        ZEND_ARG_INFO(0, needle)
                    273:        ZEND_ARG_INFO(0, offset)
                    274:        ZEND_ARG_INFO(0, encoding)
                    275: ZEND_END_ARG_INFO()
                    276: 
                    277: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_stripos, 0, 0, 2)
                    278:        ZEND_ARG_INFO(0, haystack)
                    279:        ZEND_ARG_INFO(0, needle)
                    280:        ZEND_ARG_INFO(0, offset)
                    281:        ZEND_ARG_INFO(0, encoding)
                    282: ZEND_END_ARG_INFO()
                    283: 
                    284: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_strripos, 0, 0, 2)
                    285:        ZEND_ARG_INFO(0, haystack)
                    286:        ZEND_ARG_INFO(0, needle)
                    287:        ZEND_ARG_INFO(0, offset)
                    288:        ZEND_ARG_INFO(0, encoding)
                    289: ZEND_END_ARG_INFO()
                    290: 
                    291: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_strstr, 0, 0, 2)
                    292:        ZEND_ARG_INFO(0, haystack)
                    293:        ZEND_ARG_INFO(0, needle)
                    294:        ZEND_ARG_INFO(0, part)
                    295:        ZEND_ARG_INFO(0, encoding)
                    296: ZEND_END_ARG_INFO()
                    297: 
                    298: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_strrchr, 0, 0, 2)
                    299:        ZEND_ARG_INFO(0, haystack)
                    300:        ZEND_ARG_INFO(0, needle)
                    301:        ZEND_ARG_INFO(0, part)
                    302:        ZEND_ARG_INFO(0, encoding)
                    303: ZEND_END_ARG_INFO()
                    304: 
                    305: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_stristr, 0, 0, 2)
                    306:        ZEND_ARG_INFO(0, haystack)
                    307:        ZEND_ARG_INFO(0, needle)
                    308:        ZEND_ARG_INFO(0, part)
                    309:        ZEND_ARG_INFO(0, encoding)
                    310: ZEND_END_ARG_INFO()
                    311: 
                    312: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_strrichr, 0, 0, 2)
                    313:        ZEND_ARG_INFO(0, haystack)
                    314:        ZEND_ARG_INFO(0, needle)
                    315:        ZEND_ARG_INFO(0, part)
                    316:        ZEND_ARG_INFO(0, encoding)
                    317: ZEND_END_ARG_INFO()
                    318: 
                    319: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_substr_count, 0, 0, 2)
                    320:        ZEND_ARG_INFO(0, haystack)
                    321:        ZEND_ARG_INFO(0, needle)
                    322:        ZEND_ARG_INFO(0, encoding)
                    323: ZEND_END_ARG_INFO()
                    324: 
                    325: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_substr, 0, 0, 2)
                    326:        ZEND_ARG_INFO(0, str)
                    327:        ZEND_ARG_INFO(0, start)
                    328:        ZEND_ARG_INFO(0, length)
                    329:        ZEND_ARG_INFO(0, encoding)
                    330: ZEND_END_ARG_INFO()
                    331: 
                    332: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_strcut, 0, 0, 2)
                    333:        ZEND_ARG_INFO(0, str)
                    334:        ZEND_ARG_INFO(0, start)
                    335:        ZEND_ARG_INFO(0, length)
                    336:        ZEND_ARG_INFO(0, encoding)
                    337: ZEND_END_ARG_INFO()
                    338: 
                    339: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_strwidth, 0, 0, 1)
                    340:        ZEND_ARG_INFO(0, str)
                    341:        ZEND_ARG_INFO(0, encoding)
                    342: ZEND_END_ARG_INFO()
                    343: 
                    344: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_strimwidth, 0, 0, 3)
                    345:        ZEND_ARG_INFO(0, str)
                    346:        ZEND_ARG_INFO(0, start)
                    347:        ZEND_ARG_INFO(0, width)
                    348:        ZEND_ARG_INFO(0, trimmarker)
                    349:        ZEND_ARG_INFO(0, encoding)
                    350: ZEND_END_ARG_INFO()
                    351: 
                    352: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_convert_encoding, 0, 0, 2)
                    353:        ZEND_ARG_INFO(0, str)
                    354:        ZEND_ARG_INFO(0, to)
                    355:        ZEND_ARG_INFO(0, from)
                    356: ZEND_END_ARG_INFO()
                    357: 
                    358: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_convert_case, 0, 0, 2)
                    359:        ZEND_ARG_INFO(0, sourcestring)
                    360:        ZEND_ARG_INFO(0, mode)
                    361:        ZEND_ARG_INFO(0, encoding)
                    362: ZEND_END_ARG_INFO()
                    363: 
                    364: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_strtoupper, 0, 0, 1)
                    365:        ZEND_ARG_INFO(0, sourcestring)
                    366:        ZEND_ARG_INFO(0, encoding)
                    367: ZEND_END_ARG_INFO()
                    368: 
                    369: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_strtolower, 0, 0, 1)
                    370:        ZEND_ARG_INFO(0, sourcestring)
                    371:        ZEND_ARG_INFO(0, encoding)
                    372: ZEND_END_ARG_INFO()
                    373: 
                    374: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_detect_encoding, 0, 0, 1)
                    375:        ZEND_ARG_INFO(0, str)
                    376:        ZEND_ARG_INFO(0, encoding_list)
                    377:        ZEND_ARG_INFO(0, strict)
                    378: ZEND_END_ARG_INFO()
                    379: 
                    380: ZEND_BEGIN_ARG_INFO(arginfo_mb_list_encodings, 0)
                    381: ZEND_END_ARG_INFO()
                    382: 
                    383: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_encoding_aliases, 0, 0, 1)
                    384:        ZEND_ARG_INFO(0, encoding)
                    385: ZEND_END_ARG_INFO()
                    386: 
                    387: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_encode_mimeheader, 0, 0, 1)
                    388:        ZEND_ARG_INFO(0, str)
                    389:        ZEND_ARG_INFO(0, charset)
                    390:        ZEND_ARG_INFO(0, transfer)
                    391:        ZEND_ARG_INFO(0, linefeed)
                    392:        ZEND_ARG_INFO(0, indent)
                    393: ZEND_END_ARG_INFO()
                    394: 
                    395: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_decode_mimeheader, 0, 0, 1)
                    396:        ZEND_ARG_INFO(0, string)
                    397: ZEND_END_ARG_INFO()
                    398: 
                    399: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_convert_kana, 0, 0, 1)
                    400:        ZEND_ARG_INFO(0, str)
                    401:        ZEND_ARG_INFO(0, option)
                    402:        ZEND_ARG_INFO(0, encoding)
                    403: ZEND_END_ARG_INFO()
                    404: 
                    405: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_convert_variables, 1, 0, 3)
                    406:        ZEND_ARG_INFO(0, to)
                    407:        ZEND_ARG_INFO(0, from)
                    408:        ZEND_ARG_INFO(1, ...)
                    409: ZEND_END_ARG_INFO()
                    410: 
                    411: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_encode_numericentity, 0, 0, 2)
                    412:        ZEND_ARG_INFO(0, string)
                    413:        ZEND_ARG_INFO(0, convmap)
                    414:        ZEND_ARG_INFO(0, encoding)
1.1.1.2   misho     415:        ZEND_ARG_INFO(0, is_hex)
1.1       misho     416: ZEND_END_ARG_INFO()
                    417: 
                    418: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_decode_numericentity, 0, 0, 2)
                    419:        ZEND_ARG_INFO(0, string)
                    420:        ZEND_ARG_INFO(0, convmap)
                    421:        ZEND_ARG_INFO(0, encoding)
                    422: ZEND_END_ARG_INFO()
                    423: 
                    424: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_send_mail, 0, 0, 3)
                    425:        ZEND_ARG_INFO(0, to)
                    426:        ZEND_ARG_INFO(0, subject)
                    427:        ZEND_ARG_INFO(0, message)
                    428:        ZEND_ARG_INFO(0, additional_headers)
                    429:        ZEND_ARG_INFO(0, additional_parameters)
                    430: ZEND_END_ARG_INFO()
                    431: 
                    432: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_get_info, 0, 0, 0)
                    433:        ZEND_ARG_INFO(0, type)
                    434: ZEND_END_ARG_INFO()
                    435: 
                    436: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_check_encoding, 0, 0, 0)
                    437:        ZEND_ARG_INFO(0, var)
                    438:        ZEND_ARG_INFO(0, encoding)
                    439: ZEND_END_ARG_INFO()
                    440: 
                    441: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_regex_encoding, 0, 0, 0)
                    442:        ZEND_ARG_INFO(0, encoding)
                    443: ZEND_END_ARG_INFO()
                    444: 
                    445: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_ereg, 0, 0, 2)
                    446:        ZEND_ARG_INFO(0, pattern)
                    447:        ZEND_ARG_INFO(0, string)
                    448:        ZEND_ARG_INFO(1, registers)
                    449: ZEND_END_ARG_INFO()
                    450: 
                    451: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_eregi, 0, 0, 2)
                    452:        ZEND_ARG_INFO(0, pattern)
                    453:        ZEND_ARG_INFO(0, string)
                    454:        ZEND_ARG_INFO(1, registers)
                    455: ZEND_END_ARG_INFO()
                    456: 
                    457: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_ereg_replace, 0, 0, 3)
                    458:        ZEND_ARG_INFO(0, pattern)
                    459:        ZEND_ARG_INFO(0, replacement)
                    460:        ZEND_ARG_INFO(0, string)
                    461:        ZEND_ARG_INFO(0, option)
                    462: ZEND_END_ARG_INFO()
                    463: 
                    464: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_eregi_replace, 0, 0, 3)
                    465:        ZEND_ARG_INFO(0, pattern)
                    466:        ZEND_ARG_INFO(0, replacement)
                    467:        ZEND_ARG_INFO(0, string)
                    468: ZEND_END_ARG_INFO()
                    469: 
1.1.1.2   misho     470: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_ereg_replace_callback, 0, 0, 3)
                    471:        ZEND_ARG_INFO(0, pattern)
                    472:        ZEND_ARG_INFO(0, callback)
                    473:        ZEND_ARG_INFO(0, string)
                    474:        ZEND_ARG_INFO(0, option)
                    475: ZEND_END_ARG_INFO()
                    476:  
1.1       misho     477: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_split, 0, 0, 2)
                    478:        ZEND_ARG_INFO(0, pattern)
                    479:        ZEND_ARG_INFO(0, string)
                    480:        ZEND_ARG_INFO(0, limit)
                    481: ZEND_END_ARG_INFO()
                    482: 
                    483: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_ereg_match, 0, 0, 2)
                    484:        ZEND_ARG_INFO(0, pattern)
                    485:        ZEND_ARG_INFO(0, string)
                    486:        ZEND_ARG_INFO(0, option)
                    487: ZEND_END_ARG_INFO()
                    488: 
                    489: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_ereg_search, 0, 0, 0)
                    490:        ZEND_ARG_INFO(0, pattern)
                    491:        ZEND_ARG_INFO(0, option)
                    492: ZEND_END_ARG_INFO()
                    493: 
                    494: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_ereg_search_pos, 0, 0, 0)
                    495:        ZEND_ARG_INFO(0, pattern)
                    496:        ZEND_ARG_INFO(0, option)
                    497: ZEND_END_ARG_INFO()
                    498: 
                    499: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_ereg_search_regs, 0, 0, 0)
                    500:        ZEND_ARG_INFO(0, pattern)
                    501:        ZEND_ARG_INFO(0, option)
                    502: ZEND_END_ARG_INFO()
                    503: 
                    504: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_ereg_search_init, 0, 0, 1)
                    505:        ZEND_ARG_INFO(0, string)
                    506:        ZEND_ARG_INFO(0, pattern)
                    507:        ZEND_ARG_INFO(0, option)
                    508: ZEND_END_ARG_INFO()
                    509: 
                    510: ZEND_BEGIN_ARG_INFO(arginfo_mb_ereg_search_getregs, 0)
                    511: ZEND_END_ARG_INFO()
                    512: 
                    513: ZEND_BEGIN_ARG_INFO(arginfo_mb_ereg_search_getpos, 0)
                    514: ZEND_END_ARG_INFO()
                    515: 
                    516: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_ereg_search_setpos, 0, 0, 1)
                    517:        ZEND_ARG_INFO(0, position)
                    518: ZEND_END_ARG_INFO()
                    519: 
                    520: ZEND_BEGIN_ARG_INFO_EX(arginfo_mb_regex_set_options, 0, 0, 0)
                    521:        ZEND_ARG_INFO(0, options)
                    522: ZEND_END_ARG_INFO()
                    523: /* }}} */
                    524: 
                    525: /* {{{ zend_function_entry mbstring_functions[] */
                    526: const zend_function_entry mbstring_functions[] = {
                    527:        PHP_FE(mb_convert_case,                 arginfo_mb_convert_case)
                    528:        PHP_FE(mb_strtoupper,                   arginfo_mb_strtoupper)
                    529:        PHP_FE(mb_strtolower,                   arginfo_mb_strtolower)
                    530:        PHP_FE(mb_language,                             arginfo_mb_language)
                    531:        PHP_FE(mb_internal_encoding,    arginfo_mb_internal_encoding)
                    532:        PHP_FE(mb_http_input,                   arginfo_mb_http_input)
                    533:        PHP_FE(mb_http_output,                  arginfo_mb_http_output)
                    534:        PHP_FE(mb_detect_order,                 arginfo_mb_detect_order)
                    535:        PHP_FE(mb_substitute_character, arginfo_mb_substitute_character)
                    536:        PHP_FE(mb_parse_str,                    arginfo_mb_parse_str)
                    537:        PHP_FE(mb_output_handler,               arginfo_mb_output_handler)
                    538:        PHP_FE(mb_preferred_mime_name,  arginfo_mb_preferred_mime_name)
                    539:        PHP_FE(mb_strlen,                               arginfo_mb_strlen)
                    540:        PHP_FE(mb_strpos,                               arginfo_mb_strpos)
                    541:        PHP_FE(mb_strrpos,                              arginfo_mb_strrpos)
                    542:        PHP_FE(mb_stripos,                              arginfo_mb_stripos)
                    543:        PHP_FE(mb_strripos,                             arginfo_mb_strripos)
                    544:        PHP_FE(mb_strstr,                               arginfo_mb_strstr)
                    545:        PHP_FE(mb_strrchr,                              arginfo_mb_strrchr)
                    546:        PHP_FE(mb_stristr,                              arginfo_mb_stristr)
                    547:        PHP_FE(mb_strrichr,                             arginfo_mb_strrichr)
                    548:        PHP_FE(mb_substr_count,                 arginfo_mb_substr_count)
                    549:        PHP_FE(mb_substr,                               arginfo_mb_substr)
                    550:        PHP_FE(mb_strcut,                               arginfo_mb_strcut)
                    551:        PHP_FE(mb_strwidth,                             arginfo_mb_strwidth)
                    552:        PHP_FE(mb_strimwidth,                   arginfo_mb_strimwidth)
                    553:        PHP_FE(mb_convert_encoding,             arginfo_mb_convert_encoding)
                    554:        PHP_FE(mb_detect_encoding,              arginfo_mb_detect_encoding)
                    555:        PHP_FE(mb_list_encodings,               arginfo_mb_list_encodings)
                    556:        PHP_FE(mb_encoding_aliases,             arginfo_mb_encoding_aliases)
                    557:        PHP_FE(mb_convert_kana,                 arginfo_mb_convert_kana)
                    558:        PHP_FE(mb_encode_mimeheader,    arginfo_mb_encode_mimeheader)
                    559:        PHP_FE(mb_decode_mimeheader,    arginfo_mb_decode_mimeheader)
                    560:        PHP_FE(mb_convert_variables,    arginfo_mb_convert_variables)
                    561:        PHP_FE(mb_encode_numericentity, arginfo_mb_encode_numericentity)
                    562:        PHP_FE(mb_decode_numericentity, arginfo_mb_decode_numericentity)
                    563:        PHP_FE(mb_send_mail,                    arginfo_mb_send_mail)
                    564:        PHP_FE(mb_get_info,                             arginfo_mb_get_info)
                    565:        PHP_FE(mb_check_encoding,               arginfo_mb_check_encoding)
                    566: #if HAVE_MBREGEX
                    567:        PHP_MBREGEX_FUNCTION_ENTRIES
                    568: #endif
                    569:        PHP_FE_END
                    570: };
                    571: /* }}} */
                    572: 
                    573: /* {{{ zend_module_entry mbstring_module_entry */
                    574: zend_module_entry mbstring_module_entry = {
1.1.1.2   misho     575:        STANDARD_MODULE_HEADER,
1.1       misho     576:        "mbstring",
                    577:        mbstring_functions,
                    578:        PHP_MINIT(mbstring),
                    579:        PHP_MSHUTDOWN(mbstring),
                    580:        PHP_RINIT(mbstring),
                    581:        PHP_RSHUTDOWN(mbstring),
                    582:        PHP_MINFO(mbstring),
1.1.1.2   misho     583:        NO_VERSION_YET,
                    584:        PHP_MODULE_GLOBALS(mbstring),
                    585:        PHP_GINIT(mbstring),
                    586:        PHP_GSHUTDOWN(mbstring),
                    587:        NULL,
1.1       misho     588:        STANDARD_MODULE_PROPERTIES_EX
                    589: };
                    590: /* }}} */
                    591: 
                    592: /* {{{ static sapi_post_entry php_post_entries[] */
                    593: static sapi_post_entry php_post_entries[] = {
                    594:        { DEFAULT_POST_CONTENT_TYPE, sizeof(DEFAULT_POST_CONTENT_TYPE)-1, sapi_read_standard_form_data, php_std_post_handler },
                    595:        { MULTIPART_CONTENT_TYPE,    sizeof(MULTIPART_CONTENT_TYPE)-1,    NULL,                         rfc1867_post_handler },
                    596:        { NULL, 0, NULL, NULL }
                    597: };
                    598: /* }}} */
                    599: 
                    600: #ifdef COMPILE_DL_MBSTRING
                    601: ZEND_GET_MODULE(mbstring)
                    602: #endif
                    603: 
                    604: /* {{{ allocators */
                    605: static void *_php_mb_allocators_malloc(unsigned int sz)
                    606: {
                    607:        return emalloc(sz);
                    608: }
                    609: 
                    610: static void *_php_mb_allocators_realloc(void *ptr, unsigned int sz)
                    611: {
                    612:        return erealloc(ptr, sz);
                    613: }
                    614: 
                    615: static void *_php_mb_allocators_calloc(unsigned int nelems, unsigned int szelem)
                    616: {
                    617:        return ecalloc(nelems, szelem);
                    618: }
                    619: 
                    620: static void _php_mb_allocators_free(void *ptr)
                    621: {
                    622:        efree(ptr);
                    623: } 
                    624: 
                    625: static void *_php_mb_allocators_pmalloc(unsigned int sz)
                    626: {
                    627:        return pemalloc(sz, 1);
                    628: }
                    629: 
                    630: static void *_php_mb_allocators_prealloc(void *ptr, unsigned int sz)
                    631: {
                    632:        return perealloc(ptr, sz, 1);
                    633: }
                    634: 
                    635: static void _php_mb_allocators_pfree(void *ptr)
                    636: {
                    637:        pefree(ptr, 1);
                    638: } 
                    639: 
                    640: static mbfl_allocators _php_mb_allocators = {
                    641:        _php_mb_allocators_malloc,
                    642:        _php_mb_allocators_realloc,
                    643:        _php_mb_allocators_calloc,
                    644:        _php_mb_allocators_free,
                    645:        _php_mb_allocators_pmalloc,
                    646:        _php_mb_allocators_prealloc,
                    647:        _php_mb_allocators_pfree
                    648: };
                    649: /* }}} */
                    650: 
                    651: /* {{{ static sapi_post_entry mbstr_post_entries[] */
                    652: static sapi_post_entry mbstr_post_entries[] = {
                    653:        { DEFAULT_POST_CONTENT_TYPE, sizeof(DEFAULT_POST_CONTENT_TYPE)-1, sapi_read_standard_form_data, php_mb_post_handler },
                    654:        { MULTIPART_CONTENT_TYPE,    sizeof(MULTIPART_CONTENT_TYPE)-1,    NULL,                         rfc1867_post_handler },
                    655:        { NULL, 0, NULL, NULL }
                    656: };
                    657: /* }}} */
                    658: 
                    659: /* {{{ static int php_mb_parse_encoding_list()
                    660:  *  Return 0 if input contains any illegal encoding, otherwise 1.
                    661:  *  Even if any illegal encoding is detected the result may contain a list 
                    662:  *  of parsed encodings.
                    663:  */
                    664: static int
1.1.1.2   misho     665: php_mb_parse_encoding_list(const char *value, size_t value_length, const mbfl_encoding ***return_list, size_t *return_size, int persistent TSRMLS_DC)
1.1       misho     666: {
1.1.1.2   misho     667:        int size, bauto, ret = SUCCESS;
                    668:        size_t n;
1.1       misho     669:        char *p, *p1, *p2, *endp, *tmpstr;
1.1.1.2   misho     670:        const mbfl_encoding **entry, **list;
1.1       misho     671: 
                    672:        list = NULL;
                    673:        if (value == NULL || value_length <= 0) {
                    674:                if (return_list) {
                    675:                        *return_list = NULL;
                    676:                }
                    677:                if (return_size) {
                    678:                        *return_size = 0;
                    679:                }
1.1.1.2   misho     680:                return FAILURE;
1.1       misho     681:        } else {
                    682:                /* copy the value string for work */
                    683:                if (value[0]=='"' && value[value_length-1]=='"' && value_length>2) {
                    684:                        tmpstr = (char *)estrndup(value+1, value_length-2);
                    685:                        value_length -= 2;
                    686:                }
                    687:                else
                    688:                        tmpstr = (char *)estrndup(value, value_length);
                    689:                if (tmpstr == NULL) {
1.1.1.2   misho     690:                        return FAILURE;
1.1       misho     691:                }
                    692:                /* count the number of listed encoding names */
                    693:                endp = tmpstr + value_length;
                    694:                n = 1;
                    695:                p1 = tmpstr;
                    696:                while ((p2 = php_memnstr(p1, ",", 1, endp)) != NULL) {
                    697:                        p1 = p2 + 1;
                    698:                        n++;
                    699:                }
1.1.1.2   misho     700:                size = n + MBSTRG(default_detect_order_list_size);
1.1       misho     701:                /* make list */
1.1.1.2   misho     702:                list = (const mbfl_encoding **)pecalloc(size, sizeof(mbfl_encoding*), persistent);
1.1       misho     703:                if (list != NULL) {
                    704:                        entry = list;
                    705:                        n = 0;
                    706:                        bauto = 0;
                    707:                        p1 = tmpstr;
                    708:                        do {
                    709:                                p2 = p = php_memnstr(p1, ",", 1, endp);
                    710:                                if (p == NULL) {
                    711:                                        p = endp;
                    712:                                }
                    713:                                *p = '\0';
                    714:                                /* trim spaces */
                    715:                                while (p1 < p && (*p1 == ' ' || *p1 == '\t')) {
                    716:                                        p1++;
                    717:                                }
                    718:                                p--;
                    719:                                while (p > p1 && (*p == ' ' || *p == '\t')) {
                    720:                                        *p = '\0';
                    721:                                        p--;
                    722:                                }
                    723:                                /* convert to the encoding number and check encoding */
                    724:                                if (strcasecmp(p1, "auto") == 0) {
                    725:                                        if (!bauto) {
1.1.1.2   misho     726:                                                const enum mbfl_no_encoding *src = MBSTRG(default_detect_order_list);
                    727:                                                const size_t identify_list_size = MBSTRG(default_detect_order_list_size);
                    728:                                                size_t i;
1.1       misho     729:                                                bauto = 1;
1.1.1.2   misho     730:                                                for (i = 0; i < identify_list_size; i++) {
                    731:                                                        *entry++ = mbfl_no2encoding(*src++);
1.1       misho     732:                                                        n++;
                    733:                                                }
                    734:                                        }
                    735:                                } else {
1.1.1.2   misho     736:                                        const mbfl_encoding *encoding = mbfl_name2encoding(p1);
                    737:                                        if (encoding) {
                    738:                                                *entry++ = encoding;
1.1       misho     739:                                                n++;
                    740:                                        } else {
                    741:                                                ret = 0;
                    742:                                        }
                    743:                                }
                    744:                                p1 = p2 + 1;
                    745:                        } while (n < size && p2 != NULL);
                    746:                        if (n > 0) {
                    747:                                if (return_list) {
                    748:                                        *return_list = list;
                    749:                                } else {
                    750:                                        pefree(list, persistent);
                    751:                                }
                    752:                        } else {
                    753:                                pefree(list, persistent);
                    754:                                if (return_list) {
                    755:                                        *return_list = NULL;
                    756:                                }
                    757:                                ret = 0;
                    758:                        }
                    759:                        if (return_size) {
                    760:                                *return_size = n;
                    761:                        }
                    762:                } else {
                    763:                        if (return_list) {
                    764:                                *return_list = NULL;
                    765:                        }
                    766:                        if (return_size) {
                    767:                                *return_size = 0;
                    768:                        }
                    769:                        ret = 0;
                    770:                }
                    771:                efree(tmpstr);
                    772:        }
                    773: 
                    774:        return ret;
                    775: }
                    776: /* }}} */
                    777: 
                    778: /* {{{ static int php_mb_parse_encoding_array()
                    779:  *  Return 0 if input contains any illegal encoding, otherwise 1.
                    780:  *  Even if any illegal encoding is detected the result may contain a list 
                    781:  *  of parsed encodings.
                    782:  */
                    783: static int
1.1.1.2   misho     784: php_mb_parse_encoding_array(zval *array, const mbfl_encoding ***return_list, size_t *return_size, int persistent TSRMLS_DC)
1.1       misho     785: {
                    786:        zval **hash_entry;
                    787:        HashTable *target_hash;
1.1.1.2   misho     788:        int i, n, size, bauto, ret = SUCCESS;
                    789:        const mbfl_encoding **list, **entry;
1.1       misho     790: 
                    791:        list = NULL;
                    792:        if (Z_TYPE_P(array) == IS_ARRAY) {
                    793:                target_hash = Z_ARRVAL_P(array);
                    794:                zend_hash_internal_pointer_reset(target_hash);
                    795:                i = zend_hash_num_elements(target_hash);
1.1.1.2   misho     796:                size = i + MBSTRG(default_detect_order_list_size);
                    797:                list = (const mbfl_encoding **)pecalloc(size, sizeof(mbfl_encoding*), persistent);
1.1       misho     798:                if (list != NULL) {
                    799:                        entry = list;
                    800:                        bauto = 0;
                    801:                        n = 0;
                    802:                        while (i > 0) {
                    803:                                if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) {
                    804:                                        break;
                    805:                                }
                    806:                                convert_to_string_ex(hash_entry);
                    807:                                if (strcasecmp(Z_STRVAL_PP(hash_entry), "auto") == 0) {
                    808:                                        if (!bauto) {
1.1.1.2   misho     809:                                                const enum mbfl_no_encoding *src = MBSTRG(default_detect_order_list);
                    810:                                                const size_t identify_list_size = MBSTRG(default_detect_order_list_size);
                    811:                                                size_t j;
                    812: 
1.1       misho     813:                                                bauto = 1;
1.1.1.2   misho     814:                                                for (j = 0; j < identify_list_size; j++) {
                    815:                                                        *entry++ = mbfl_no2encoding(*src++);
1.1       misho     816:                                                        n++;
                    817:                                                }
                    818:                                        }
                    819:                                } else {
1.1.1.2   misho     820:                                        const mbfl_encoding *encoding = mbfl_name2encoding(Z_STRVAL_PP(hash_entry));
                    821:                                        if (encoding) {
                    822:                                                *entry++ = encoding;
1.1       misho     823:                                                n++;
                    824:                                        } else {
1.1.1.2   misho     825:                                                ret = FAILURE;
1.1       misho     826:                                        }
                    827:                                }
                    828:                                zend_hash_move_forward(target_hash);
                    829:                                i--;
                    830:                        }
                    831:                        if (n > 0) {
                    832:                                if (return_list) {
                    833:                                        *return_list = list;
                    834:                                } else {
                    835:                                        pefree(list, persistent);
                    836:                                }
                    837:                        } else {
                    838:                                pefree(list, persistent);
                    839:                                if (return_list) {
                    840:                                        *return_list = NULL;
                    841:                                }
1.1.1.2   misho     842:                                ret = FAILURE;
1.1       misho     843:                        }
                    844:                        if (return_size) {
                    845:                                *return_size = n;
                    846:                        }
                    847:                } else {
                    848:                        if (return_list) {
                    849:                                *return_list = NULL;
                    850:                        }
                    851:                        if (return_size) {
                    852:                                *return_size = 0;
                    853:                        }
1.1.1.2   misho     854:                        ret = FAILURE;
1.1       misho     855:                }
                    856:        }
                    857: 
                    858:        return ret;
                    859: }
                    860: /* }}} */
                    861: 
1.1.1.2   misho     862: /* {{{ zend_multibyte interface */
                    863: static const zend_encoding* php_mb_zend_encoding_fetcher(const char *encoding_name TSRMLS_DC)
                    864: {
                    865:        return (const zend_encoding*)mbfl_name2encoding(encoding_name);
                    866: }
                    867: 
                    868: static const char *php_mb_zend_encoding_name_getter(const zend_encoding *encoding)
                    869: {
                    870:        return ((const mbfl_encoding *)encoding)->name;
                    871: }
                    872: 
                    873: static int php_mb_zend_encoding_lexer_compatibility_checker(const zend_encoding *_encoding)
                    874: {
                    875:        const mbfl_encoding *encoding = (const mbfl_encoding*)_encoding;
                    876:        if (encoding->flag & MBFL_ENCTYPE_SBCS) {
                    877:                return 1;
                    878:        }
                    879:        if ((encoding->flag & (MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE)) == MBFL_ENCTYPE_MBCS) {
                    880:                return 1;
                    881:        }
                    882:        return 0;
                    883: }
                    884: 
                    885: static const zend_encoding *php_mb_zend_encoding_detector(const unsigned char *arg_string, size_t arg_length, const zend_encoding **list, size_t list_size TSRMLS_DC)
                    886: {
                    887:        mbfl_string string;
                    888: 
                    889:        if (!list) {
                    890:                list = (const zend_encoding **)MBSTRG(current_detect_order_list);
                    891:                list_size = MBSTRG(current_detect_order_list_size);
                    892:        }
                    893: 
                    894:        mbfl_string_init(&string);
                    895:        string.no_language = MBSTRG(language);
                    896:        string.val = (unsigned char *)arg_string;
                    897:        string.len = arg_length;
                    898:        return (const zend_encoding *) mbfl_identify_encoding2(&string, (const mbfl_encoding **)list, list_size, 0);
                    899: }
                    900: 
                    901: static size_t php_mb_zend_encoding_converter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length, const zend_encoding *encoding_to, const zend_encoding *encoding_from TSRMLS_DC)
                    902: {
                    903:        mbfl_string string, result;
                    904:        mbfl_buffer_converter *convd;
                    905:        int status, loc;
                    906: 
                    907:        /* new encoding */
                    908:        /* initialize string */
                    909:        mbfl_string_init(&string);
                    910:        mbfl_string_init(&result);
                    911:        string.no_encoding = ((const mbfl_encoding*)encoding_from)->no_encoding;
                    912:        string.no_language = MBSTRG(language);
                    913:        string.val = (unsigned char*)from;
                    914:        string.len = from_length;
                    915: 
                    916:        /* initialize converter */
                    917:        convd = mbfl_buffer_converter_new2((const mbfl_encoding *)encoding_from, (const mbfl_encoding *)encoding_to, string.len);
                    918:        if (convd == NULL) {
                    919:                return -1;
                    920:        }
                    921:        mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
                    922:        mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
                    923: 
                    924:        /* do it */
                    925:        status = mbfl_buffer_converter_feed2(convd, &string, &loc);
                    926:        if (status) {
                    927:                mbfl_buffer_converter_delete(convd);
                    928:                return (size_t)-1;
                    929:        }
                    930: 
                    931:        mbfl_buffer_converter_flush(convd);
                    932:        if (!mbfl_buffer_converter_result(convd, &result)) {
                    933:                mbfl_buffer_converter_delete(convd);
                    934:                return (size_t)-1;
                    935:        }       
                    936: 
                    937:        *to = result.val;
                    938:        *to_length = result.len;
                    939: 
                    940:        mbfl_buffer_converter_delete(convd);
                    941: 
                    942:        return loc;
                    943: }
                    944: 
                    945: static int php_mb_zend_encoding_list_parser(const char *encoding_list, size_t encoding_list_len, const zend_encoding ***return_list, size_t *return_size, int persistent TSRMLS_DC)
                    946: {
                    947:        return php_mb_parse_encoding_list(encoding_list, encoding_list_len, (const mbfl_encoding ***)return_list, return_size, persistent TSRMLS_CC);
                    948: }
                    949: 
                    950: static const zend_encoding *php_mb_zend_internal_encoding_getter(TSRMLS_D)
                    951: {
                    952:        return (const zend_encoding *)MBSTRG(internal_encoding);
                    953: }
                    954: 
                    955: static int php_mb_zend_internal_encoding_setter(const zend_encoding *encoding TSRMLS_DC)
                    956: {
                    957:        MBSTRG(internal_encoding) = (const mbfl_encoding *)encoding;
                    958:        return SUCCESS;
                    959: }
                    960: 
                    961: static zend_multibyte_functions php_mb_zend_multibyte_functions = {
                    962:        "mbstring",
                    963:        php_mb_zend_encoding_fetcher,
                    964:        php_mb_zend_encoding_name_getter,
                    965:        php_mb_zend_encoding_lexer_compatibility_checker,
                    966:        php_mb_zend_encoding_detector,
                    967:        php_mb_zend_encoding_converter,
                    968:        php_mb_zend_encoding_list_parser,
                    969:        php_mb_zend_internal_encoding_getter,
                    970:        php_mb_zend_internal_encoding_setter
                    971: };
                    972: /* }}} */
                    973: 
1.1       misho     974: static void *_php_mb_compile_regex(const char *pattern TSRMLS_DC);
                    975: static int _php_mb_match_regex(void *opaque, const char *str, size_t str_len);
                    976: static void _php_mb_free_regex(void *opaque);
                    977: 
                    978: #if HAVE_ONIG
                    979: /* {{{ _php_mb_compile_regex */
                    980: static void *_php_mb_compile_regex(const char *pattern TSRMLS_DC)
                    981: {
                    982:        php_mb_regex_t *retval;
                    983:        OnigErrorInfo err_info;
                    984:        int err_code;
                    985: 
                    986:        if ((err_code = onig_new(&retval,
                    987:                        (const OnigUChar *)pattern,
                    988:                        (const OnigUChar *)pattern + strlen(pattern),
                    989:                        ONIG_OPTION_IGNORECASE | ONIG_OPTION_DONT_CAPTURE_GROUP,
                    990:                        ONIG_ENCODING_ASCII, &OnigSyntaxPerl, &err_info))) {
                    991:                OnigUChar err_str[ONIG_MAX_ERROR_MESSAGE_LEN];
                    992:                onig_error_code_to_str(err_str, err_code, err_info);
                    993:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %s", pattern, err_str);
                    994:                retval = NULL;
                    995:        }
                    996:        return retval;
                    997: }
                    998: /* }}} */
                    999: 
                   1000: /* {{{ _php_mb_match_regex */
                   1001: static int _php_mb_match_regex(void *opaque, const char *str, size_t str_len)
                   1002: {
                   1003:        return onig_search((php_mb_regex_t *)opaque, (const OnigUChar *)str,
                   1004:                        (const OnigUChar*)str + str_len, (const OnigUChar *)str,
                   1005:                        (const OnigUChar*)str + str_len, NULL, ONIG_OPTION_NONE) >= 0;
                   1006: }
                   1007: /* }}} */
                   1008: 
                   1009: /* {{{ _php_mb_free_regex */
                   1010: static void _php_mb_free_regex(void *opaque)
                   1011: {
                   1012:        onig_free((php_mb_regex_t *)opaque);
                   1013: }
                   1014: /* }}} */
                   1015: #elif HAVE_PCRE || HAVE_BUNDLED_PCRE
                   1016: /* {{{ _php_mb_compile_regex */
                   1017: static void *_php_mb_compile_regex(const char *pattern TSRMLS_DC)
                   1018: {
                   1019:        pcre *retval;
                   1020:        const char *err_str;
                   1021:        int err_offset;
                   1022: 
                   1023:        if (!(retval = pcre_compile(pattern,
                   1024:                        PCRE_CASELESS, &err_str, &err_offset, NULL))) {
                   1025:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s (offset=%d): %s", pattern, err_offset, err_str);
                   1026:        }
                   1027:        return retval;
                   1028: }
                   1029: /* }}} */
                   1030: 
                   1031: /* {{{ _php_mb_match_regex */
                   1032: static int _php_mb_match_regex(void *opaque, const char *str, size_t str_len)
                   1033: {
                   1034:        return pcre_exec((pcre *)opaque, NULL, str, (int)str_len, 0,
                   1035:                        0, NULL, 0) >= 0;
                   1036: }
                   1037: /* }}} */
                   1038: 
                   1039: /* {{{ _php_mb_free_regex */
                   1040: static void _php_mb_free_regex(void *opaque)
                   1041: {
                   1042:        pcre_free(opaque);
                   1043: }
                   1044: /* }}} */
                   1045: #endif
                   1046: 
                   1047: /* {{{ php_mb_nls_get_default_detect_order_list */
1.1.1.2   misho    1048: static int php_mb_nls_get_default_detect_order_list(enum mbfl_no_language lang, enum mbfl_no_encoding **plist, size_t *plist_size)
1.1       misho    1049: {
                   1050:        size_t i;
                   1051: 
                   1052:        *plist = (enum mbfl_no_encoding *) php_mb_default_identify_list_neut;
                   1053:        *plist_size = sizeof(php_mb_default_identify_list_neut) / sizeof(php_mb_default_identify_list_neut[0]);
                   1054: 
                   1055:        for (i = 0; i < sizeof(php_mb_default_identify_list) / sizeof(php_mb_default_identify_list[0]); i++) {
                   1056:                if (php_mb_default_identify_list[i].lang == lang) {
                   1057:                        *plist = (enum mbfl_no_encoding *)php_mb_default_identify_list[i].list;
                   1058:                        *plist_size = php_mb_default_identify_list[i].list_size;
                   1059:                        return 1;
                   1060:                }
                   1061:        }
                   1062:        return 0;
                   1063: }
                   1064: /* }}} */
                   1065: 
1.1.1.2   misho    1066: static char *php_mb_rfc1867_substring_conf(const zend_encoding *encoding, char *start, int len, char quote TSRMLS_DC)
                   1067: {
                   1068:        char *result = emalloc(len + 2);
                   1069:        char *resp = result;
                   1070:        int i;
                   1071: 
                   1072:        for (i = 0; i < len && start[i] != quote; ++i) {
                   1073:                if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
                   1074:                        *resp++ = start[++i];
                   1075:                } else {
                   1076:                        size_t j = php_mb_mbchar_bytes_ex(start+i, (const mbfl_encoding *)encoding);
                   1077: 
                   1078:                        while (j-- > 0 && i < len) {
                   1079:                                *resp++ = start[i++];
                   1080:                        }
                   1081:                        --i;
                   1082:                }
                   1083:        }
                   1084: 
                   1085:        *resp = '\0';
                   1086:        return result;
                   1087: }
                   1088: 
                   1089: static char *php_mb_rfc1867_getword(const zend_encoding *encoding, char **line, char stop TSRMLS_DC) /* {{{ */
                   1090: {
                   1091:        char *pos = *line, quote;
                   1092:        char *res;
                   1093: 
                   1094:        while (*pos && *pos != stop) {
                   1095:                if ((quote = *pos) == '"' || quote == '\'') {
                   1096:                        ++pos;
                   1097:                        while (*pos && *pos != quote) {
                   1098:                                if (*pos == '\\' && pos[1] && pos[1] == quote) {
                   1099:                                        pos += 2;
                   1100:                                } else {
                   1101:                                        ++pos;
                   1102:                                }
                   1103:                        }
                   1104:                        if (*pos) {
                   1105:                                ++pos;
                   1106:                        }
                   1107:                } else {
                   1108:                        pos += php_mb_mbchar_bytes_ex(pos, (const mbfl_encoding *)encoding);
                   1109: 
                   1110:                }
                   1111:        }
                   1112:        if (*pos == '\0') {
                   1113:                res = estrdup(*line);
                   1114:                *line += strlen(*line);
                   1115:                return res;
                   1116:        }
                   1117: 
                   1118:        res = estrndup(*line, pos - *line);
                   1119: 
                   1120:        while (*pos == stop) {
                   1121:                pos += php_mb_mbchar_bytes_ex(pos, (const mbfl_encoding *)encoding);
                   1122:        }
                   1123: 
                   1124:        *line = pos;
                   1125:        return res;
                   1126: }
                   1127: /* }}} */
                   1128: 
                   1129: static char *php_mb_rfc1867_getword_conf(const zend_encoding *encoding, char *str TSRMLS_DC) /* {{{ */
                   1130: {
                   1131:        while (*str && isspace(*(unsigned char *)str)) {
                   1132:                ++str;
                   1133:        }
                   1134: 
                   1135:        if (!*str) {
                   1136:                return estrdup("");
                   1137:        }
                   1138: 
                   1139:        if (*str == '"' || *str == '\'') {
                   1140:                char quote = *str;
                   1141: 
                   1142:                str++;
                   1143:                return php_mb_rfc1867_substring_conf(encoding, str, strlen(str), quote TSRMLS_CC);
                   1144:        } else {
                   1145:                char *strend = str;
                   1146: 
                   1147:                while (*strend && !isspace(*(unsigned char *)strend)) {
                   1148:                        ++strend;
                   1149:                }
                   1150:                return php_mb_rfc1867_substring_conf(encoding, str, strend - str, 0 TSRMLS_CC);
                   1151:        }
                   1152: }
                   1153: /* }}} */
                   1154: 
                   1155: static char *php_mb_rfc1867_basename(const zend_encoding *encoding, char *filename TSRMLS_DC) /* {{{ */
                   1156: {
                   1157:        char *s, *s2;
                   1158:        const size_t filename_len = strlen(filename);
                   1159: 
                   1160:        /* The \ check should technically be needed for win32 systems only where
                   1161:         * it is a valid path separator. However, IE in all it's wisdom always sends
                   1162:         * the full path of the file on the user's filesystem, which means that unless
                   1163:         * the user does basename() they get a bogus file name. Until IE's user base drops
                   1164:         * to nill or problem is fixed this code must remain enabled for all systems. */
                   1165:        s = php_mb_safe_strrchr_ex(filename, '\\', filename_len, (const mbfl_encoding *)encoding);
                   1166:        s2 = php_mb_safe_strrchr_ex(filename, '/', filename_len, (const mbfl_encoding *)encoding);
                   1167:        
                   1168:        if (s && s2) {
                   1169:                if (s > s2) {
                   1170:                        return ++s;
                   1171:                } else {
                   1172:                        return ++s2;
                   1173:                }
                   1174:        } else if (s) {
                   1175:                return ++s;
                   1176:        } else if (s2) {
                   1177:                return ++s2;
                   1178:        } else {
                   1179:                return filename;
                   1180:        }
                   1181: }
                   1182: /* }}} */
                   1183: 
1.1       misho    1184: /* {{{ php.ini directive handler */
                   1185: /* {{{ static PHP_INI_MH(OnUpdate_mbstring_language) */
                   1186: static PHP_INI_MH(OnUpdate_mbstring_language)
                   1187: {
                   1188:        enum mbfl_no_language no_language;
                   1189: 
                   1190:        no_language = mbfl_name2no_language(new_value);
                   1191:        if (no_language == mbfl_no_language_invalid) {
                   1192:                MBSTRG(language) = mbfl_no_language_neutral;
                   1193:                return FAILURE;
                   1194:        }
                   1195:        MBSTRG(language) = no_language;
                   1196:        php_mb_nls_get_default_detect_order_list(no_language, &MBSTRG(default_detect_order_list), &MBSTRG(default_detect_order_list_size));
                   1197:        return SUCCESS;
                   1198: }
                   1199: /* }}} */
                   1200: 
                   1201: /* {{{ static PHP_INI_MH(OnUpdate_mbstring_detect_order) */
                   1202: static PHP_INI_MH(OnUpdate_mbstring_detect_order)
                   1203: {
1.1.1.2   misho    1204:        const mbfl_encoding **list;
                   1205:        size_t size;
1.1       misho    1206: 
1.1.1.2   misho    1207:        if (!new_value) {
1.1       misho    1208:                if (MBSTRG(detect_order_list)) {
1.1.1.2   misho    1209:                        pefree(MBSTRG(detect_order_list), 1);
1.1       misho    1210:                }
1.1.1.2   misho    1211:                MBSTRG(detect_order_list) = NULL;
                   1212:                MBSTRG(detect_order_list_size) = 0;
                   1213:                return SUCCESS;
                   1214:        }
                   1215: 
                   1216:        if (FAILURE == php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
1.1       misho    1217:                return FAILURE;
                   1218:        }
                   1219: 
1.1.1.2   misho    1220:        if (MBSTRG(detect_order_list)) {
                   1221:                pefree(MBSTRG(detect_order_list), 1);
                   1222:        }
                   1223:        MBSTRG(detect_order_list) = list;
                   1224:        MBSTRG(detect_order_list_size) = size;
1.1       misho    1225:        return SUCCESS;
                   1226: }
                   1227: /* }}} */
                   1228: 
                   1229: /* {{{ static PHP_INI_MH(OnUpdate_mbstring_http_input) */
                   1230: static PHP_INI_MH(OnUpdate_mbstring_http_input)
                   1231: {
1.1.1.2   misho    1232:        const mbfl_encoding **list;
                   1233:        size_t size;
1.1       misho    1234: 
1.1.1.2   misho    1235:        if (!new_value) {
1.1       misho    1236:                if (MBSTRG(http_input_list)) {
1.1.1.2   misho    1237:                        pefree(MBSTRG(http_input_list), 1);
1.1       misho    1238:                }
1.1.1.2   misho    1239:                MBSTRG(http_input_list) = NULL;
1.1       misho    1240:                MBSTRG(http_input_list_size) = 0;
1.1.1.2   misho    1241:                return SUCCESS;
                   1242:        }
                   1243: 
                   1244:        if (FAILURE == php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
1.1       misho    1245:                return FAILURE;
                   1246:        }
                   1247: 
1.1.1.2   misho    1248:        if (MBSTRG(http_input_list)) {
                   1249:                pefree(MBSTRG(http_input_list), 1);
                   1250:        }
                   1251:        MBSTRG(http_input_list) = list;
                   1252:        MBSTRG(http_input_list_size) = size;
                   1253: 
1.1       misho    1254:        return SUCCESS;
                   1255: }
                   1256: /* }}} */
                   1257: 
                   1258: /* {{{ static PHP_INI_MH(OnUpdate_mbstring_http_output) */
                   1259: static PHP_INI_MH(OnUpdate_mbstring_http_output)
                   1260: {
1.1.1.2   misho    1261:        const mbfl_encoding *encoding;
1.1       misho    1262: 
1.1.1.2   misho    1263:        if (new_value == NULL || new_value_length == 0) {
                   1264:                MBSTRG(http_output_encoding) = &mbfl_encoding_pass;
                   1265:                MBSTRG(current_http_output_encoding) = &mbfl_encoding_pass;
                   1266:                return SUCCESS;
                   1267:        }
                   1268: 
                   1269:        encoding = mbfl_name2encoding(new_value);
                   1270:        if (!encoding) {
                   1271:                MBSTRG(http_output_encoding) = &mbfl_encoding_pass;
                   1272:                MBSTRG(current_http_output_encoding) = &mbfl_encoding_pass;
                   1273:                return FAILURE;
1.1       misho    1274:        }
                   1275: 
1.1.1.2   misho    1276:        MBSTRG(http_output_encoding) = encoding;
                   1277:        MBSTRG(current_http_output_encoding) = encoding;
1.1       misho    1278:        return SUCCESS;
                   1279: }
                   1280: /* }}} */
                   1281: 
                   1282: /* {{{ static _php_mb_ini_mbstring_internal_encoding_set */
                   1283: int _php_mb_ini_mbstring_internal_encoding_set(const char *new_value, uint new_value_length TSRMLS_DC)
                   1284: {
1.1.1.2   misho    1285:        const mbfl_encoding *encoding;
                   1286: 
                   1287:        if (!new_value || new_value_length == 0 || !(encoding = mbfl_name2encoding(new_value))) {
1.1       misho    1288:                switch (MBSTRG(language)) {
                   1289:                        case mbfl_no_language_uni:
1.1.1.2   misho    1290:                                encoding = mbfl_no2encoding(mbfl_no_encoding_utf8);
1.1       misho    1291:                                break;
                   1292:                        case mbfl_no_language_japanese:
1.1.1.2   misho    1293:                                encoding = mbfl_no2encoding(mbfl_no_encoding_euc_jp);
1.1       misho    1294:                                break;
                   1295:                        case mbfl_no_language_korean:
1.1.1.2   misho    1296:                                encoding = mbfl_no2encoding(mbfl_no_encoding_euc_kr);
1.1       misho    1297:                                break;
                   1298:                        case mbfl_no_language_simplified_chinese:
1.1.1.2   misho    1299:                                encoding = mbfl_no2encoding(mbfl_no_encoding_euc_cn);
1.1       misho    1300:                                break;
                   1301:                        case mbfl_no_language_traditional_chinese:
1.1.1.2   misho    1302:                                encoding = mbfl_no2encoding(mbfl_no_encoding_euc_tw);
1.1       misho    1303:                                break;
                   1304:                        case mbfl_no_language_russian:
1.1.1.2   misho    1305:                                encoding = mbfl_no2encoding(mbfl_no_encoding_koi8r);
1.1       misho    1306:                                break;
                   1307:                        case mbfl_no_language_german:
1.1.1.2   misho    1308:                                encoding = mbfl_no2encoding(mbfl_no_encoding_8859_15);
1.1       misho    1309:                                break;
                   1310:                        case mbfl_no_language_armenian:
1.1.1.2   misho    1311:                                encoding = mbfl_no2encoding(mbfl_no_encoding_armscii8);
1.1       misho    1312:                                break;
                   1313:                        case mbfl_no_language_turkish:
1.1.1.2   misho    1314:                                encoding = mbfl_no2encoding(mbfl_no_encoding_8859_9);
1.1       misho    1315:                                break;
                   1316:                        default:
1.1.1.2   misho    1317:                                encoding = mbfl_no2encoding(mbfl_no_encoding_8859_1);
1.1       misho    1318:                                break;
                   1319:                }
                   1320:        }
1.1.1.2   misho    1321:        MBSTRG(internal_encoding) = encoding;
                   1322:        MBSTRG(current_internal_encoding) = encoding;
1.1       misho    1323: #if HAVE_MBREGEX
                   1324:        {
                   1325:                const char *enc_name = new_value;
                   1326:                if (FAILURE == php_mb_regex_set_default_mbctype(enc_name TSRMLS_CC)) {
                   1327:                        /* falls back to EUC-JP if an unknown encoding name is given */
                   1328:                        enc_name = "EUC-JP";
                   1329:                        php_mb_regex_set_default_mbctype(enc_name TSRMLS_CC);
                   1330:                }
                   1331:                php_mb_regex_set_mbctype(new_value TSRMLS_CC);
                   1332:        }
                   1333: #endif
                   1334:        return SUCCESS;
                   1335: }
                   1336: /* }}} */
                   1337: 
                   1338: /* {{{ static PHP_INI_MH(OnUpdate_mbstring_internal_encoding) */
                   1339: static PHP_INI_MH(OnUpdate_mbstring_internal_encoding)
                   1340: {
1.1.1.2   misho    1341:        if (OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC) == FAILURE) {
                   1342:                return FAILURE;
                   1343:        }
1.1       misho    1344:        if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN
                   1345:                        || stage == PHP_INI_STAGE_RUNTIME) {
                   1346:                return _php_mb_ini_mbstring_internal_encoding_set(new_value, new_value_length TSRMLS_CC);
                   1347:        } else {
                   1348:                /* the corresponding mbstring globals needs to be set according to the
                   1349:                 * ini value in the later stage because it never falls back to the
                   1350:                 * default value if 1. no value for mbstring.internal_encoding is given,
                   1351:                 * 2. mbstring.language directive is processed in per-dir or runtime
                   1352:                 * context and 3. call to the handler for mbstring.language is done
                   1353:                 * after mbstring.internal_encoding is handled. */
                   1354:                return SUCCESS;
                   1355:        }
                   1356: }
                   1357: /* }}} */
                   1358: 
                   1359: /* {{{ static PHP_INI_MH(OnUpdate_mbstring_substitute_character) */
                   1360: static PHP_INI_MH(OnUpdate_mbstring_substitute_character)
                   1361: {
                   1362:        int c;
                   1363:        char *endptr = NULL;
                   1364: 
                   1365:        if (new_value != NULL) {
                   1366:                if (strcasecmp("none", new_value) == 0) {
                   1367:                        MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE;
                   1368:                        MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE;
                   1369:                } else if (strcasecmp("long", new_value) == 0) {
                   1370:                        MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG;
                   1371:                        MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG;
                   1372:                } else if (strcasecmp("entity", new_value) == 0) {
                   1373:                        MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY;
                   1374:                        MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY;
                   1375:                } else {
                   1376:                        MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
                   1377:                        MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
                   1378:                        if (new_value_length >0) {
                   1379:                                c = strtol(new_value, &endptr, 0);
                   1380:                                if (*endptr == '\0') {
                   1381:                                        MBSTRG(filter_illegal_substchar) = c;
                   1382:                                        MBSTRG(current_filter_illegal_substchar) = c;
                   1383:                                }
                   1384:                        }
                   1385:                }
                   1386:        } else {
                   1387:                MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
                   1388:                MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
                   1389:                MBSTRG(filter_illegal_substchar) = 0x3f;        /* '?' */
                   1390:                MBSTRG(current_filter_illegal_substchar) = 0x3f;        /* '?' */
                   1391:        }
                   1392: 
                   1393:        return SUCCESS;
                   1394: }
                   1395: /* }}} */
                   1396: 
                   1397: /* {{{ static PHP_INI_MH(OnUpdate_mbstring_encoding_translation) */
                   1398: static PHP_INI_MH(OnUpdate_mbstring_encoding_translation)
                   1399: {
                   1400:        if (new_value == NULL) {
1.1.1.2   misho    1401:                return FAILURE;
1.1       misho    1402:        }
                   1403: 
                   1404:        OnUpdateBool(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
                   1405: 
                   1406:        if (MBSTRG(encoding_translation)) {
                   1407:                sapi_unregister_post_entry(php_post_entries TSRMLS_CC);
                   1408:                sapi_register_post_entries(mbstr_post_entries TSRMLS_CC);
                   1409:        } else {
                   1410:                sapi_unregister_post_entry(mbstr_post_entries TSRMLS_CC);
                   1411:                sapi_register_post_entries(php_post_entries TSRMLS_CC);
                   1412:        }
                   1413: 
                   1414:        return SUCCESS;
                   1415: }
                   1416: /* }}} */
                   1417: 
                   1418: /* {{{ static PHP_INI_MH(OnUpdate_mbstring_http_output_conv_mimetypes */
                   1419: static PHP_INI_MH(OnUpdate_mbstring_http_output_conv_mimetypes)
                   1420: {
                   1421:        zval tmp;
                   1422:        void *re = NULL;
                   1423: 
                   1424:        if (!new_value) {
                   1425:                new_value = entry->orig_value;
                   1426:                new_value_length = entry->orig_value_length;
                   1427:        }
                   1428:        php_trim(new_value, new_value_length, NULL, 0, &tmp, 3 TSRMLS_CC);
                   1429: 
                   1430:        if (Z_STRLEN(tmp) > 0) {
                   1431:                if (!(re = _php_mb_compile_regex(Z_STRVAL(tmp) TSRMLS_CC))) {
                   1432:                        zval_dtor(&tmp);
                   1433:                        return FAILURE;
                   1434:                }
                   1435:        }
                   1436: 
                   1437:        if (MBSTRG(http_output_conv_mimetypes)) {
                   1438:                _php_mb_free_regex(MBSTRG(http_output_conv_mimetypes));
                   1439:        }
                   1440: 
                   1441:        MBSTRG(http_output_conv_mimetypes) = re;
                   1442: 
                   1443:        zval_dtor(&tmp);
                   1444:        return SUCCESS;
                   1445: }
                   1446: /* }}} */
                   1447: /* }}} */
                   1448: 
                   1449: /* {{{ php.ini directive registration */
                   1450: PHP_INI_BEGIN()
                   1451:        PHP_INI_ENTRY("mbstring.language", "neutral", PHP_INI_ALL, OnUpdate_mbstring_language)
                   1452:        PHP_INI_ENTRY("mbstring.detect_order", NULL, PHP_INI_ALL, OnUpdate_mbstring_detect_order)
                   1453:        PHP_INI_ENTRY("mbstring.http_input", "pass", PHP_INI_ALL, OnUpdate_mbstring_http_input)
                   1454:        PHP_INI_ENTRY("mbstring.http_output", "pass", PHP_INI_ALL, OnUpdate_mbstring_http_output)
1.1.1.2   misho    1455:        STD_PHP_INI_ENTRY("mbstring.internal_encoding", NULL, PHP_INI_ALL, OnUpdate_mbstring_internal_encoding, internal_encoding_name, zend_mbstring_globals, mbstring_globals)
1.1       misho    1456:        PHP_INI_ENTRY("mbstring.substitute_character", NULL, PHP_INI_ALL, OnUpdate_mbstring_substitute_character)
                   1457:        STD_PHP_INI_ENTRY("mbstring.func_overload", "0", 
                   1458:        PHP_INI_SYSTEM, OnUpdateLong, func_overload, zend_mbstring_globals, mbstring_globals)
                   1459: 
                   1460:        STD_PHP_INI_BOOLEAN("mbstring.encoding_translation", "0",
                   1461:                PHP_INI_SYSTEM | PHP_INI_PERDIR,
                   1462:                OnUpdate_mbstring_encoding_translation, 
                   1463:                encoding_translation, zend_mbstring_globals, mbstring_globals)                                   
                   1464:        PHP_INI_ENTRY("mbstring.http_output_conv_mimetypes",
                   1465:                "^(text/|application/xhtml\\+xml)",
                   1466:                PHP_INI_ALL,
                   1467:                OnUpdate_mbstring_http_output_conv_mimetypes)
                   1468: 
                   1469:        STD_PHP_INI_BOOLEAN("mbstring.strict_detection", "0",
                   1470:                PHP_INI_ALL,
                   1471:                OnUpdateLong,
                   1472:                strict_detection, zend_mbstring_globals, mbstring_globals)
                   1473: PHP_INI_END()
                   1474: /* }}} */
                   1475: 
                   1476: /* {{{ module global initialize handler */
                   1477: static PHP_GINIT_FUNCTION(mbstring)
                   1478: {
                   1479:        mbstring_globals->language = mbfl_no_language_uni;
1.1.1.2   misho    1480:        mbstring_globals->internal_encoding = NULL;
1.1       misho    1481:        mbstring_globals->current_internal_encoding = mbstring_globals->internal_encoding;
1.1.1.2   misho    1482:        mbstring_globals->http_output_encoding = &mbfl_encoding_pass;
                   1483:        mbstring_globals->current_http_output_encoding = &mbfl_encoding_pass;
                   1484:        mbstring_globals->http_input_identify = NULL;
                   1485:        mbstring_globals->http_input_identify_get = NULL;
                   1486:        mbstring_globals->http_input_identify_post = NULL;
                   1487:        mbstring_globals->http_input_identify_cookie = NULL;
                   1488:        mbstring_globals->http_input_identify_string = NULL;
1.1       misho    1489:        mbstring_globals->http_input_list = NULL;
                   1490:        mbstring_globals->http_input_list_size = 0;
                   1491:        mbstring_globals->detect_order_list = NULL;
                   1492:        mbstring_globals->detect_order_list_size = 0;
                   1493:        mbstring_globals->current_detect_order_list = NULL;
                   1494:        mbstring_globals->current_detect_order_list_size = 0;
                   1495:        mbstring_globals->default_detect_order_list = (enum mbfl_no_encoding *) php_mb_default_identify_list_neut;
                   1496:        mbstring_globals->default_detect_order_list_size = sizeof(php_mb_default_identify_list_neut) / sizeof(php_mb_default_identify_list_neut[0]);
                   1497:        mbstring_globals->filter_illegal_mode = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
                   1498:        mbstring_globals->filter_illegal_substchar = 0x3f;      /* '?' */
                   1499:        mbstring_globals->current_filter_illegal_mode = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
                   1500:        mbstring_globals->current_filter_illegal_substchar = 0x3f;      /* '?' */
                   1501:        mbstring_globals->illegalchars = 0;
                   1502:        mbstring_globals->func_overload = 0;
                   1503:        mbstring_globals->encoding_translation = 0;
                   1504:        mbstring_globals->strict_detection = 0;
                   1505:        mbstring_globals->outconv = NULL;
                   1506:        mbstring_globals->http_output_conv_mimetypes = NULL;
                   1507: #if HAVE_MBREGEX
                   1508:        mbstring_globals->mb_regex_globals = php_mb_regex_globals_alloc(TSRMLS_C);
                   1509: #endif
                   1510: }
                   1511: /* }}} */
                   1512: 
                   1513: /* {{{ PHP_GSHUTDOWN_FUNCTION */
                   1514: static PHP_GSHUTDOWN_FUNCTION(mbstring)
                   1515: {
                   1516:        if (mbstring_globals->http_input_list) {
                   1517:                free(mbstring_globals->http_input_list);
                   1518:        }
                   1519:        if (mbstring_globals->detect_order_list) {
                   1520:                free(mbstring_globals->detect_order_list);
                   1521:        }
                   1522:        if (mbstring_globals->http_output_conv_mimetypes) {
                   1523:                _php_mb_free_regex(mbstring_globals->http_output_conv_mimetypes);
                   1524:        }
                   1525: #if HAVE_MBREGEX
                   1526:        php_mb_regex_globals_free(mbstring_globals->mb_regex_globals TSRMLS_CC);
                   1527: #endif
                   1528: }
                   1529: /* }}} */
                   1530: 
                   1531: /* {{{ PHP_MINIT_FUNCTION(mbstring) */
                   1532: PHP_MINIT_FUNCTION(mbstring)
                   1533: {
                   1534:        __mbfl_allocators = &_php_mb_allocators;
                   1535: 
                   1536:        REGISTER_INI_ENTRIES();
                   1537: 
                   1538:        /* This is a global handler. Should not be set in a per-request handler. */
1.1.1.2   misho    1539:        sapi_register_treat_data(mbstr_treat_data TSRMLS_CC);
1.1       misho    1540: 
                   1541:        /* Post handlers are stored in the thread-local context. */
                   1542:        if (MBSTRG(encoding_translation)) {
                   1543:                sapi_register_post_entries(mbstr_post_entries TSRMLS_CC);
                   1544:        }
                   1545: 
                   1546:        REGISTER_LONG_CONSTANT("MB_OVERLOAD_MAIL", MB_OVERLOAD_MAIL, CONST_CS | CONST_PERSISTENT);
                   1547:        REGISTER_LONG_CONSTANT("MB_OVERLOAD_STRING", MB_OVERLOAD_STRING, CONST_CS | CONST_PERSISTENT);
                   1548:        REGISTER_LONG_CONSTANT("MB_OVERLOAD_REGEX", MB_OVERLOAD_REGEX, CONST_CS | CONST_PERSISTENT);
                   1549: 
                   1550:        REGISTER_LONG_CONSTANT("MB_CASE_UPPER", PHP_UNICODE_CASE_UPPER, CONST_CS | CONST_PERSISTENT);
                   1551:        REGISTER_LONG_CONSTANT("MB_CASE_LOWER", PHP_UNICODE_CASE_LOWER, CONST_CS | CONST_PERSISTENT);
                   1552:        REGISTER_LONG_CONSTANT("MB_CASE_TITLE", PHP_UNICODE_CASE_TITLE, CONST_CS | CONST_PERSISTENT);
                   1553: 
                   1554: #if HAVE_MBREGEX
                   1555:        PHP_MINIT(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
                   1556: #endif
1.1.1.2   misho    1557: 
                   1558:        if (FAILURE == zend_multibyte_set_functions(&php_mb_zend_multibyte_functions TSRMLS_CC)) {
                   1559:                return FAILURE;
                   1560:        }
                   1561: 
                   1562:        php_rfc1867_set_multibyte_callbacks(
                   1563:                php_mb_encoding_translation,
                   1564:                php_mb_gpc_get_detect_order,
                   1565:                php_mb_gpc_set_input_encoding,
                   1566:                php_mb_rfc1867_getword,
                   1567:                php_mb_rfc1867_getword_conf,
                   1568:                php_mb_rfc1867_basename);
                   1569: 
1.1       misho    1570:        return SUCCESS;
                   1571: }
                   1572: /* }}} */
                   1573: 
                   1574: /* {{{ PHP_MSHUTDOWN_FUNCTION(mbstring) */
                   1575: PHP_MSHUTDOWN_FUNCTION(mbstring)
                   1576: {
                   1577:        UNREGISTER_INI_ENTRIES();
1.1.1.2   misho    1578: 
1.1       misho    1579: #if HAVE_MBREGEX
                   1580:        PHP_MSHUTDOWN(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
                   1581: #endif
                   1582: 
                   1583:        return SUCCESS;
                   1584: }
                   1585: /* }}} */
                   1586: 
                   1587: /* {{{ PHP_RINIT_FUNCTION(mbstring) */
                   1588: PHP_RINIT_FUNCTION(mbstring)
                   1589: {
                   1590:        zend_function *func, *orig;
                   1591:        const struct mb_overload_def *p;
                   1592: 
                   1593:        MBSTRG(current_internal_encoding) = MBSTRG(internal_encoding);
                   1594:        MBSTRG(current_http_output_encoding) = MBSTRG(http_output_encoding);
                   1595:        MBSTRG(current_filter_illegal_mode) = MBSTRG(filter_illegal_mode);
                   1596:        MBSTRG(current_filter_illegal_substchar) = MBSTRG(filter_illegal_substchar);
                   1597: 
                   1598:        MBSTRG(illegalchars) = 0;
                   1599: 
1.1.1.2   misho    1600:        php_mb_populate_current_detect_order_list(TSRMLS_C);
1.1       misho    1601: 
                   1602:        /* override original function. */
                   1603:        if (MBSTRG(func_overload)){
                   1604:                p = &(mb_ovld[0]);
                   1605:                
                   1606:                while (p->type > 0) {
                   1607:                        if ((MBSTRG(func_overload) & p->type) == p->type && 
                   1608:                                zend_hash_find(EG(function_table), p->save_func,
                   1609:                                        strlen(p->save_func)+1, (void **)&orig) != SUCCESS) {
                   1610: 
                   1611:                                zend_hash_find(EG(function_table), p->ovld_func, strlen(p->ovld_func)+1 , (void **)&func);
                   1612:                                
                   1613:                                if (zend_hash_find(EG(function_table), p->orig_func, strlen(p->orig_func)+1, (void **)&orig) != SUCCESS) {
                   1614:                                        php_error_docref("ref.mbstring" TSRMLS_CC, E_WARNING, "mbstring couldn't find function %s.", p->orig_func);
                   1615:                                        return FAILURE;
                   1616:                                } else {
                   1617:                                        zend_hash_add(EG(function_table), p->save_func, strlen(p->save_func)+1, orig, sizeof(zend_function), NULL);
                   1618: 
                   1619:                                        if (zend_hash_update(EG(function_table), p->orig_func, strlen(p->orig_func)+1, func, sizeof(zend_function), 
                   1620:                                                NULL) == FAILURE) {
                   1621:                                                php_error_docref("ref.mbstring" TSRMLS_CC, E_WARNING, "mbstring couldn't replace function %s.", p->orig_func);
                   1622:                                                return FAILURE;
                   1623:                                        }
                   1624:                                }
                   1625:                        }
                   1626:                        p++;
                   1627:                }
                   1628:        }
                   1629: #if HAVE_MBREGEX
                   1630:        PHP_RINIT(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
                   1631: #endif
1.1.1.2   misho    1632:        zend_multibyte_set_internal_encoding((const zend_encoding *)MBSTRG(internal_encoding) TSRMLS_CC);
1.1       misho    1633: 
                   1634:        return SUCCESS;
                   1635: }
                   1636: /* }}} */
                   1637: 
                   1638: /* {{{ PHP_RSHUTDOWN_FUNCTION(mbstring) */
                   1639: PHP_RSHUTDOWN_FUNCTION(mbstring)
                   1640: {
                   1641:        const struct mb_overload_def *p;
                   1642:        zend_function *orig;
                   1643: 
                   1644:        if (MBSTRG(current_detect_order_list) != NULL) {
                   1645:                efree(MBSTRG(current_detect_order_list));
                   1646:                MBSTRG(current_detect_order_list) = NULL;
                   1647:                MBSTRG(current_detect_order_list_size) = 0;
                   1648:        }
                   1649:        if (MBSTRG(outconv) != NULL) {
                   1650:                MBSTRG(illegalchars) += mbfl_buffer_illegalchars(MBSTRG(outconv));
                   1651:                mbfl_buffer_converter_delete(MBSTRG(outconv));
                   1652:                MBSTRG(outconv) = NULL;
                   1653:        }
                   1654: 
                   1655:        /* clear http input identification. */
1.1.1.2   misho    1656:        MBSTRG(http_input_identify) = NULL;
                   1657:        MBSTRG(http_input_identify_post) = NULL;
                   1658:        MBSTRG(http_input_identify_get) = NULL;
                   1659:        MBSTRG(http_input_identify_cookie) = NULL;
                   1660:        MBSTRG(http_input_identify_string) = NULL;
1.1       misho    1661: 
                   1662:        /*  clear overloaded function. */
                   1663:        if (MBSTRG(func_overload)){
                   1664:                p = &(mb_ovld[0]);
                   1665:                while (p->type > 0) {
                   1666:                        if ((MBSTRG(func_overload) & p->type) == p->type && 
                   1667:                                zend_hash_find(EG(function_table), p->save_func,
                   1668:                                                           strlen(p->save_func)+1, (void **)&orig) == SUCCESS) {
                   1669:                                
                   1670:                                zend_hash_update(EG(function_table), p->orig_func, strlen(p->orig_func)+1, orig, sizeof(zend_function), NULL);
                   1671:                                zend_hash_del(EG(function_table), p->save_func, strlen(p->save_func)+1);
                   1672:                        }
                   1673:                        p++;
                   1674:                }
                   1675:        }
                   1676: 
                   1677: #if HAVE_MBREGEX
                   1678:        PHP_RSHUTDOWN(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
                   1679: #endif
                   1680: 
                   1681:        return SUCCESS;
                   1682: }
                   1683: /* }}} */
                   1684: 
                   1685: /* {{{ PHP_MINFO_FUNCTION(mbstring) */
                   1686: PHP_MINFO_FUNCTION(mbstring)
                   1687: {
                   1688:        php_info_print_table_start();
                   1689:        php_info_print_table_row(2, "Multibyte Support", "enabled");
                   1690:        php_info_print_table_row(2, "Multibyte string engine", "libmbfl");
1.1.1.2   misho    1691:        php_info_print_table_row(2, "HTTP input encoding translation", MBSTRG(encoding_translation) ? "enabled": "disabled");
                   1692:        {
                   1693:                char tmp[256];
                   1694:                snprintf(tmp, sizeof(tmp), "%d.%d.%d", MBFL_VERSION_MAJOR, MBFL_VERSION_MINOR, MBFL_VERSION_TEENY);
                   1695:                php_info_print_table_row(2, "libmbfl version", tmp);
                   1696:        }       
1.1       misho    1697:        php_info_print_table_end();
                   1698: 
                   1699:        php_info_print_table_start();
                   1700:        php_info_print_table_header(1, "mbstring extension makes use of \"streamable kanji code filter and converter\", which is distributed under the GNU Lesser General Public License version 2.1.");
                   1701:        php_info_print_table_end();
                   1702: 
                   1703: #if HAVE_MBREGEX
                   1704:        PHP_MINFO(mb_regex)(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
                   1705: #endif
                   1706: 
                   1707:        DISPLAY_INI_ENTRIES();
                   1708: }
                   1709: /* }}} */
                   1710: 
                   1711: /* {{{ proto string mb_language([string language])
                   1712:    Sets the current language or Returns the current language as a string */
                   1713: PHP_FUNCTION(mb_language)
                   1714: {
                   1715:        char *name = NULL;
                   1716:        int name_len = 0;
                   1717: 
                   1718:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) {
                   1719:                return;
                   1720:        }
                   1721:        if (name == NULL) {
                   1722:                RETVAL_STRING((char *)mbfl_no_language2name(MBSTRG(language)), 1);
                   1723:        } else {
                   1724:                if (FAILURE == zend_alter_ini_entry(
                   1725:                                "mbstring.language", sizeof("mbstring.language"),
                   1726:                                name, name_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME)) {
                   1727:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown language \"%s\"", name);
                   1728:                        RETVAL_FALSE;
                   1729:                } else {
                   1730:                        RETVAL_TRUE;
                   1731:                }
                   1732:        }
                   1733: }
                   1734: /* }}} */
                   1735: 
                   1736: /* {{{ proto string mb_internal_encoding([string encoding])
                   1737:    Sets the current internal encoding or Returns the current internal encoding as a string */
                   1738: PHP_FUNCTION(mb_internal_encoding)
                   1739: {
1.1.1.2   misho    1740:        const char *name = NULL;
1.1       misho    1741:        int name_len;
1.1.1.2   misho    1742:        const mbfl_encoding *encoding;
1.1       misho    1743: 
                   1744:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) {
                   1745:                RETURN_FALSE;
                   1746:        }
                   1747:        if (name == NULL) {
1.1.1.2   misho    1748:                name = MBSTRG(current_internal_encoding) ? MBSTRG(current_internal_encoding)->name: NULL;
1.1       misho    1749:                if (name != NULL) {
                   1750:                        RETURN_STRING(name, 1);
                   1751:                } else {
                   1752:                        RETURN_FALSE;
                   1753:                }
                   1754:        } else {
1.1.1.2   misho    1755:                encoding = mbfl_name2encoding(name);
                   1756:                if (!encoding) {
1.1       misho    1757:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
                   1758:                        RETURN_FALSE;
                   1759:                } else {
1.1.1.2   misho    1760:                        MBSTRG(current_internal_encoding) = encoding;
1.1       misho    1761:                        RETURN_TRUE;
                   1762:                }
                   1763:        }
                   1764: }
                   1765: /* }}} */
                   1766: 
                   1767: /* {{{ proto mixed mb_http_input([string type])
                   1768:    Returns the input encoding */
                   1769: PHP_FUNCTION(mb_http_input)
                   1770: {
                   1771:        char *typ = NULL;
                   1772:        int typ_len;
1.1.1.2   misho    1773:        int retname;
                   1774:        char *list, *temp;
                   1775:        const mbfl_encoding *result = NULL;
1.1       misho    1776: 
                   1777:        retname = 1;
                   1778:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &typ, &typ_len) == FAILURE) {
                   1779:                RETURN_FALSE;
                   1780:        }
                   1781:        if (typ == NULL) {
                   1782:                result = MBSTRG(http_input_identify);
                   1783:        } else {
                   1784:                switch (*typ) {
                   1785:                case 'G':
                   1786:                case 'g':
                   1787:                        result = MBSTRG(http_input_identify_get);
                   1788:                        break;
                   1789:                case 'P':
                   1790:                case 'p':
                   1791:                        result = MBSTRG(http_input_identify_post);
                   1792:                        break;
                   1793:                case 'C':
                   1794:                case 'c':
                   1795:                        result = MBSTRG(http_input_identify_cookie);
                   1796:                        break;
                   1797:                case 'S':
                   1798:                case 's':
                   1799:                        result = MBSTRG(http_input_identify_string);
                   1800:                        break;
                   1801:                case 'I':
                   1802:                case 'i':
1.1.1.2   misho    1803:                        {
                   1804:                                const mbfl_encoding **entry = MBSTRG(http_input_list);
                   1805:                                const size_t n = MBSTRG(http_input_list_size);
                   1806:                                size_t i;
                   1807:                                array_init(return_value);
                   1808:                                for (i = 0; i < n; i++) {
                   1809:                                        add_next_index_string(return_value, (*entry)->name, 1);
                   1810:                                        entry++;
1.1       misho    1811:                                }
1.1.1.2   misho    1812:                                retname = 0;
1.1       misho    1813:                        }
                   1814:                        break;
                   1815:                case 'L':
                   1816:                case 'l':
1.1.1.2   misho    1817:                        {
                   1818:                                const mbfl_encoding **entry = MBSTRG(http_input_list);
                   1819:                                const size_t n = MBSTRG(http_input_list_size);
                   1820:                                size_t i;
                   1821:                                list = NULL;
                   1822:                                for (i = 0; i < n; i++) {
1.1       misho    1823:                                        if (list) {
                   1824:                                                temp = list;
1.1.1.2   misho    1825:                                                spprintf(&list, 0, "%s,%s", temp, (*entry)->name);
1.1       misho    1826:                                                efree(temp);
                   1827:                                                if (!list) { 
                   1828:                                                        break;
                   1829:                                                }
                   1830:                                        } else {
1.1.1.2   misho    1831:                                                list = estrdup((*entry)->name);
1.1       misho    1832:                                        }
1.1.1.2   misho    1833:                                        entry++;
1.1       misho    1834:                                }
                   1835:                        }
                   1836:                        if (!list) {
                   1837:                                RETURN_FALSE;
                   1838:                        }
                   1839:                        RETVAL_STRING(list, 0);
                   1840:                        retname = 0;
                   1841:                        break;
                   1842:                default:
                   1843:                        result = MBSTRG(http_input_identify);
                   1844:                        break;
                   1845:                }
                   1846:        }
                   1847: 
                   1848:        if (retname) {
1.1.1.2   misho    1849:                if (result) {
                   1850:                        RETVAL_STRING(result->name, 1);
1.1       misho    1851:                } else {
                   1852:                        RETVAL_FALSE;
                   1853:                }
                   1854:        }
                   1855: }
                   1856: /* }}} */
                   1857: 
                   1858: /* {{{ proto string mb_http_output([string encoding])
                   1859:    Sets the current output_encoding or returns the current output_encoding as a string */
                   1860: PHP_FUNCTION(mb_http_output)
                   1861: {
1.1.1.2   misho    1862:        const char *name = NULL;
1.1       misho    1863:        int name_len;
1.1.1.2   misho    1864:        const mbfl_encoding *encoding;
1.1       misho    1865: 
                   1866:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", (char **)&name, &name_len) == FAILURE) {
                   1867:                RETURN_FALSE;
                   1868:        }
                   1869: 
                   1870:        if (name == NULL) {
1.1.1.2   misho    1871:                name = MBSTRG(current_http_output_encoding) ? MBSTRG(current_http_output_encoding)->name: NULL;
1.1       misho    1872:                if (name != NULL) {
                   1873:                        RETURN_STRING(name, 1);
                   1874:                } else {
                   1875:                        RETURN_FALSE;
                   1876:                }
                   1877:        } else {
1.1.1.2   misho    1878:                encoding = mbfl_name2encoding(name);
                   1879:                if (!encoding) {
1.1       misho    1880:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
                   1881:                        RETURN_FALSE;
                   1882:                } else {
1.1.1.2   misho    1883:                        MBSTRG(current_http_output_encoding) = encoding;
1.1       misho    1884:                        RETURN_TRUE;
                   1885:                }
                   1886:        }
                   1887: }
                   1888: /* }}} */
                   1889: 
                   1890: /* {{{ proto bool|array mb_detect_order([mixed encoding-list])
                   1891:    Sets the current detect_order or Return the current detect_order as a array */
                   1892: PHP_FUNCTION(mb_detect_order)
                   1893: {
                   1894:        zval **arg1 = NULL;
                   1895: 
                   1896:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|Z", &arg1) == FAILURE) {
                   1897:                return;
                   1898:        }
                   1899: 
                   1900:        if (!arg1) {
1.1.1.2   misho    1901:                size_t i;
                   1902:                size_t n = MBSTRG(current_detect_order_list_size);
                   1903:                const mbfl_encoding **entry = MBSTRG(current_detect_order_list);
1.1       misho    1904:                array_init(return_value);
1.1.1.2   misho    1905:                for (i = 0; i < n; i++) {
                   1906:                        add_next_index_string(return_value, (*entry)->name, 1);
1.1       misho    1907:                        entry++;
                   1908:                }
                   1909:        } else {
1.1.1.2   misho    1910:                const mbfl_encoding **list = NULL;
                   1911:                size_t size = 0;
1.1       misho    1912:                switch (Z_TYPE_PP(arg1)) {
                   1913:                case IS_ARRAY:
1.1.1.2   misho    1914:                        if (FAILURE == php_mb_parse_encoding_array(*arg1, &list, &size, 0 TSRMLS_CC)) {
1.1       misho    1915:                                if (list) {
                   1916:                                        efree(list);
                   1917:                                }
                   1918:                                RETURN_FALSE;
                   1919:                        }
                   1920:                        break;
                   1921:                default:
                   1922:                        convert_to_string_ex(arg1);
1.1.1.2   misho    1923:                        if (FAILURE == php_mb_parse_encoding_list(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1), &list, &size, 0 TSRMLS_CC)) {
1.1       misho    1924:                                if (list) {
                   1925:                                        efree(list);
                   1926:                                }
                   1927:                                RETURN_FALSE;
                   1928:                        }
                   1929:                        break;
                   1930:                }
                   1931: 
                   1932:                if (list == NULL) {
                   1933:                        RETURN_FALSE;
                   1934:                }
                   1935: 
                   1936:                if (MBSTRG(current_detect_order_list)) {
                   1937:                        efree(MBSTRG(current_detect_order_list));
                   1938:                }
                   1939:                MBSTRG(current_detect_order_list) = list;
                   1940:                MBSTRG(current_detect_order_list_size) = size;
                   1941:                RETURN_TRUE;
                   1942:        }
                   1943: }
                   1944: /* }}} */
                   1945: 
                   1946: /* {{{ proto mixed mb_substitute_character([mixed substchar])
                   1947:    Sets the current substitute_character or returns the current substitute_character */
                   1948: PHP_FUNCTION(mb_substitute_character)
                   1949: {
                   1950:        zval **arg1 = NULL;
                   1951: 
                   1952:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|Z", &arg1) == FAILURE) {
                   1953:                return;
                   1954:        }
                   1955: 
                   1956:        if (!arg1) {
                   1957:                if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
                   1958:                        RETURN_STRING("none", 1);
                   1959:                } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG) {
                   1960:                        RETURN_STRING("long", 1);
                   1961:                } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY) {
                   1962:                        RETURN_STRING("entity", 1);
                   1963:                } else {
                   1964:                        RETURN_LONG(MBSTRG(current_filter_illegal_substchar));
                   1965:                }
                   1966:        } else {
                   1967:                RETVAL_TRUE;
                   1968: 
                   1969:                switch (Z_TYPE_PP(arg1)) {
                   1970:                case IS_STRING:
                   1971:                        if (strncasecmp("none", Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1)) == 0) {
                   1972:                                MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE;
                   1973:                        } else if (strncasecmp("long", Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1)) == 0) {
                   1974:                                MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG;
                   1975:                        } else if (strncasecmp("entity", Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1)) == 0) {
                   1976:                                MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY;
                   1977:                        } else {
                   1978:                                convert_to_long_ex(arg1);
                   1979: 
                   1980:                                if (Z_LVAL_PP(arg1) < 0xffff && Z_LVAL_PP(arg1) > 0x0) {
                   1981:                                        MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
                   1982:                                        MBSTRG(current_filter_illegal_substchar) = Z_LVAL_PP(arg1);
                   1983:                                } else {
                   1984:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown character.");
                   1985:                                        RETURN_FALSE;
                   1986:                                }
                   1987:                        }
                   1988:                        break;
                   1989:                default:
                   1990:                        convert_to_long_ex(arg1);
                   1991:                        if (Z_LVAL_PP(arg1) < 0xffff && Z_LVAL_PP(arg1) > 0x0) {
                   1992:                                MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
                   1993:                                MBSTRG(current_filter_illegal_substchar) = Z_LVAL_PP(arg1);
                   1994:                        } else {
                   1995:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown character.");
                   1996:                                RETURN_FALSE;
                   1997:                        }
                   1998:                        break;
                   1999:                }
                   2000:        }
                   2001: }
                   2002: /* }}} */
                   2003: 
                   2004: /* {{{ proto string mb_preferred_mime_name(string encoding)
                   2005:    Return the preferred MIME name (charset) as a string */
                   2006: PHP_FUNCTION(mb_preferred_mime_name)
                   2007: {
                   2008:        enum mbfl_no_encoding no_encoding;
                   2009:        char *name = NULL;
                   2010:        int name_len;
                   2011: 
                   2012:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
                   2013:                return;
                   2014:        } else {
                   2015:                no_encoding = mbfl_name2no_encoding(name);
                   2016:                if (no_encoding == mbfl_no_encoding_invalid) {
                   2017:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
                   2018:                        RETVAL_FALSE;
                   2019:                } else {
                   2020:                        const char *preferred_name = mbfl_no2preferred_mime_name(no_encoding);
                   2021:                        if (preferred_name == NULL || *preferred_name == '\0') {
                   2022:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No MIME preferred name corresponding to \"%s\"", name);
                   2023:                                RETVAL_FALSE;
                   2024:                        } else {
                   2025:                                RETVAL_STRING((char *)preferred_name, 1);
                   2026:                        }
                   2027:                }
                   2028:        }
                   2029: }
                   2030: /* }}} */
                   2031: 
                   2032: #define IS_SJIS1(c) ((((c)>=0x81 && (c)<=0x9f) || ((c)>=0xe0 && (c)<=0xf5)) ? 1 : 0)
                   2033: #define IS_SJIS2(c) ((((c)>=0x40 && (c)<=0x7e) || ((c)>=0x80 && (c)<=0xfc)) ? 1 : 0)
                   2034: 
                   2035: /* {{{ proto bool mb_parse_str(string encoded_string [, array result])
                   2036:    Parses GET/POST/COOKIE data and sets global variables */
                   2037: PHP_FUNCTION(mb_parse_str)
                   2038: {
                   2039:        zval *track_vars_array = NULL;
                   2040:        char *encstr = NULL;
                   2041:        int encstr_len;
                   2042:        php_mb_encoding_handler_info_t info;
1.1.1.2   misho    2043:        const mbfl_encoding *detected;
1.1       misho    2044: 
                   2045:        track_vars_array = NULL;
                   2046:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &encstr, &encstr_len, &track_vars_array) == FAILURE) {
                   2047:                return;
                   2048:        }
                   2049: 
                   2050:        if (track_vars_array != NULL) {
1.1.1.2   misho    2051:                /* Clear out the array */
1.1       misho    2052:                zval_dtor(track_vars_array);
                   2053:                array_init(track_vars_array);
                   2054:        }
                   2055: 
                   2056:        encstr = estrndup(encstr, encstr_len);
                   2057: 
                   2058:        info.data_type              = PARSE_STRING;
                   2059:        info.separator              = PG(arg_separator).input; 
                   2060:        info.report_errors          = 1;
                   2061:        info.to_encoding            = MBSTRG(current_internal_encoding);
                   2062:        info.to_language            = MBSTRG(language);
                   2063:        info.from_encodings         = MBSTRG(http_input_list);
                   2064:        info.num_from_encodings     = MBSTRG(http_input_list_size); 
                   2065:        info.from_language          = MBSTRG(language);
                   2066: 
1.1.1.2   misho    2067:        if (track_vars_array != NULL) {
                   2068:                detected = _php_mb_encoding_handler_ex(&info, track_vars_array, encstr TSRMLS_CC);
                   2069:        } else {
                   2070:                zval tmp;
                   2071:                if (!EG(active_symbol_table)) {
                   2072:                        zend_rebuild_symbol_table(TSRMLS_C);
                   2073:                }
                   2074:                Z_ARRVAL(tmp) = EG(active_symbol_table);                
                   2075:                detected = _php_mb_encoding_handler_ex(&info, &tmp, encstr TSRMLS_CC);          
                   2076:        }
1.1       misho    2077: 
                   2078:        MBSTRG(http_input_identify) = detected;
                   2079: 
1.1.1.2   misho    2080:        RETVAL_BOOL(detected);
1.1       misho    2081: 
                   2082:        if (encstr != NULL) efree(encstr);
                   2083: }
                   2084: /* }}} */
                   2085: 
                   2086: /* {{{ proto string mb_output_handler(string contents, int status)
                   2087:    Returns string in output buffer converted to the http_output encoding */
                   2088: PHP_FUNCTION(mb_output_handler)
                   2089: {
                   2090:        char *arg_string;
                   2091:        int arg_string_len;
                   2092:        long arg_status;
                   2093:        mbfl_string string, result;
                   2094:        const char *charset;
                   2095:        char *p;
1.1.1.2   misho    2096:        const mbfl_encoding *encoding;
1.1       misho    2097:        int last_feed, len;
                   2098:        unsigned char send_text_mimetype = 0;
                   2099:        char *s, *mimetype = NULL;
                   2100: 
                   2101:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &arg_string, &arg_string_len, &arg_status) == FAILURE) {
                   2102:                return;
                   2103:        }
                   2104: 
                   2105:        encoding = MBSTRG(current_http_output_encoding);
                   2106: 
                   2107:        /* start phase only */
                   2108:        if ((arg_status & PHP_OUTPUT_HANDLER_START) != 0) {
                   2109:                /* delete the converter just in case. */
                   2110:                if (MBSTRG(outconv)) {
                   2111:                        MBSTRG(illegalchars) += mbfl_buffer_illegalchars(MBSTRG(outconv));
                   2112:                        mbfl_buffer_converter_delete(MBSTRG(outconv));
                   2113:                        MBSTRG(outconv) = NULL;
                   2114:                }
1.1.1.2   misho    2115:                if (encoding == &mbfl_encoding_pass) {
1.1       misho    2116:                        RETURN_STRINGL(arg_string, arg_string_len, 1);
                   2117:                }
                   2118: 
                   2119:                /* analyze mime type */
                   2120:                if (SG(sapi_headers).mimetype &&
                   2121:                        _php_mb_match_regex(
                   2122:                                MBSTRG(http_output_conv_mimetypes),
                   2123:                                SG(sapi_headers).mimetype,
                   2124:                                strlen(SG(sapi_headers).mimetype))) {
                   2125:                        if ((s = strchr(SG(sapi_headers).mimetype,';')) == NULL){
                   2126:                                mimetype = estrdup(SG(sapi_headers).mimetype);
                   2127:                        } else {
                   2128:                                mimetype = estrndup(SG(sapi_headers).mimetype,s-SG(sapi_headers).mimetype);
                   2129:                        }
                   2130:                        send_text_mimetype = 1;
                   2131:                } else if (SG(sapi_headers).send_default_content_type) {
                   2132:                        mimetype = SG(default_mimetype) ? SG(default_mimetype) : SAPI_DEFAULT_MIMETYPE;
                   2133:                }
                   2134: 
                   2135:                /* if content-type is not yet set, set it and activate the converter */
                   2136:                if (SG(sapi_headers).send_default_content_type || send_text_mimetype) {
1.1.1.2   misho    2137:                        charset = encoding->mime_name;
1.1       misho    2138:                        if (charset) {
                   2139:                                len = spprintf( &p, 0, "Content-Type: %s; charset=%s",  mimetype, charset ); 
                   2140:                                if (sapi_add_header(p, len, 0) != FAILURE) {
                   2141:                                        SG(sapi_headers).send_default_content_type = 0;
                   2142:                                }
                   2143:                        }
                   2144:                        /* activate the converter */
1.1.1.2   misho    2145:                        MBSTRG(outconv) = mbfl_buffer_converter_new2(MBSTRG(current_internal_encoding), encoding, 0);
1.1       misho    2146:                        if (send_text_mimetype){
                   2147:                                efree(mimetype);
                   2148:                        }
                   2149:                }
                   2150:        }
                   2151: 
                   2152:        /* just return if the converter is not activated. */
                   2153:        if (MBSTRG(outconv) == NULL) {
                   2154:                RETURN_STRINGL(arg_string, arg_string_len, 1);
                   2155:        }
                   2156: 
                   2157:        /* flag */
                   2158:        last_feed = ((arg_status & PHP_OUTPUT_HANDLER_END) != 0);
                   2159:        /* mode */
                   2160:        mbfl_buffer_converter_illegal_mode(MBSTRG(outconv), MBSTRG(current_filter_illegal_mode));
                   2161:        mbfl_buffer_converter_illegal_substchar(MBSTRG(outconv), MBSTRG(current_filter_illegal_substchar));
                   2162:  
                   2163:        /* feed the string */
                   2164:        mbfl_string_init(&string);
                   2165:        string.no_language = MBSTRG(language);
1.1.1.2   misho    2166:        string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2167:        string.val = (unsigned char *)arg_string;
                   2168:        string.len = arg_string_len;
                   2169:        mbfl_buffer_converter_feed(MBSTRG(outconv), &string);
                   2170:        if (last_feed) {
                   2171:                mbfl_buffer_converter_flush(MBSTRG(outconv));
                   2172:        } 
                   2173:        /* get the converter output, and return it */
                   2174:        mbfl_buffer_converter_result(MBSTRG(outconv), &result);
                   2175:        RETVAL_STRINGL((char *)result.val, result.len, 0);              /* the string is already strdup()'ed */
                   2176:  
                   2177:        /* delete the converter if it is the last feed. */
                   2178:        if (last_feed) {
                   2179:                MBSTRG(illegalchars) += mbfl_buffer_illegalchars(MBSTRG(outconv));
                   2180:                mbfl_buffer_converter_delete(MBSTRG(outconv));
                   2181:                MBSTRG(outconv) = NULL;
                   2182:        }
                   2183: }
                   2184: /* }}} */
                   2185: 
                   2186: /* {{{ proto int mb_strlen(string str [, string encoding])
                   2187:    Get character numbers of a string */
                   2188: PHP_FUNCTION(mb_strlen)
                   2189: {
                   2190:        int n;
                   2191:        mbfl_string string;
                   2192:        char *enc_name = NULL;
                   2193:        int enc_name_len;
                   2194: 
                   2195:        mbfl_string_init(&string);
                   2196: 
                   2197:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", (char **)&string.val, &string.len, &enc_name, &enc_name_len) == FAILURE) {
                   2198:                RETURN_FALSE;
                   2199:        }
                   2200: 
                   2201:        string.no_language = MBSTRG(language);
                   2202:        if (enc_name == NULL) {
1.1.1.2   misho    2203:                string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2204:        } else {
                   2205:                string.no_encoding = mbfl_name2no_encoding(enc_name);
                   2206:                if (string.no_encoding == mbfl_no_encoding_invalid) {
                   2207:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
                   2208:                        RETURN_FALSE;
                   2209:                }
                   2210:        }
                   2211: 
                   2212:        n = mbfl_strlen(&string);
                   2213:        if (n >= 0) {
                   2214:                RETVAL_LONG(n);
                   2215:        } else {
                   2216:                RETVAL_FALSE;
                   2217:        }
                   2218: }
                   2219: /* }}} */
                   2220: 
                   2221: /* {{{ proto int mb_strpos(string haystack, string needle [, int offset [, string encoding]])
                   2222:    Find position of first occurrence of a string within another */
                   2223: PHP_FUNCTION(mb_strpos)
                   2224: {
                   2225:        int n, reverse = 0;
                   2226:        long offset;
                   2227:        mbfl_string haystack, needle;
                   2228:        char *enc_name = NULL;
                   2229:        int enc_name_len;
1.1.1.2   misho    2230: 
1.1       misho    2231:        mbfl_string_init(&haystack);
                   2232:        mbfl_string_init(&needle);
                   2233:        haystack.no_language = MBSTRG(language);
1.1.1.2   misho    2234:        haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2235:        needle.no_language = MBSTRG(language);
1.1.1.2   misho    2236:        needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2237:        offset = 0;
                   2238: 
                   2239:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &offset, &enc_name, &enc_name_len) == FAILURE) {
                   2240:                RETURN_FALSE;
                   2241:        }
                   2242: 
                   2243:        if (enc_name != NULL) {
                   2244:                haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
                   2245:                if (haystack.no_encoding == mbfl_no_encoding_invalid) {
                   2246:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
                   2247:                        RETURN_FALSE;
                   2248:                }
                   2249:        }
                   2250: 
                   2251:        if (offset < 0 || offset > mbfl_strlen(&haystack)) {
                   2252:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset not contained in string");
                   2253:                RETURN_FALSE;
                   2254:        }
                   2255:        if (needle.len == 0) {
                   2256:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
                   2257:                RETURN_FALSE;
                   2258:        }
                   2259: 
                   2260:        n = mbfl_strpos(&haystack, &needle, offset, reverse);
                   2261:        if (n >= 0) {
                   2262:                RETVAL_LONG(n);
                   2263:        } else {
                   2264:                switch (-n) {
                   2265:                case 1:
                   2266:                        break;
                   2267:                case 2:
                   2268:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Needle has not positive length");
                   2269:                        break;
                   2270:                case 4:
                   2271:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding or conversion error");
                   2272:                        break;
                   2273:                case 8:
                   2274:                        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Argument is empty");
                   2275:                        break;
                   2276:                default:
                   2277:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error in mb_strpos");
                   2278:                        break;
                   2279:                }
                   2280:                RETVAL_FALSE;
                   2281:        }
                   2282: }
                   2283: /* }}} */
                   2284: 
                   2285: /* {{{ proto int mb_strrpos(string haystack, string needle [, int offset [, string encoding]])
                   2286:    Find position of last occurrence of a string within another */
                   2287: PHP_FUNCTION(mb_strrpos)
                   2288: {
                   2289:        int n;
                   2290:        mbfl_string haystack, needle;
                   2291:        char *enc_name = NULL;
                   2292:        int enc_name_len;
                   2293:        zval **zoffset = NULL;
                   2294:        long offset = 0, str_flg;
                   2295:        char *enc_name2 = NULL;
                   2296:        int enc_name_len2;
                   2297: 
                   2298:        mbfl_string_init(&haystack);
                   2299:        mbfl_string_init(&needle);
                   2300:        haystack.no_language = MBSTRG(language);
1.1.1.2   misho    2301:        haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2302:        needle.no_language = MBSTRG(language);
1.1.1.2   misho    2303:        needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2304: 
                   2305:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|Zs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &zoffset, &enc_name, &enc_name_len) == FAILURE) {
                   2306:                RETURN_FALSE;
                   2307:        }
                   2308: 
                   2309:        if (zoffset) {
                   2310:                if (Z_TYPE_PP(zoffset) == IS_STRING) {
                   2311:                        enc_name2     = Z_STRVAL_PP(zoffset);
                   2312:                        enc_name_len2 = Z_STRLEN_PP(zoffset);
                   2313:                        str_flg       = 1;
                   2314: 
                   2315:                        if (enc_name2 != NULL) {
                   2316:                                switch (*enc_name2) {
                   2317:                                case '0':
                   2318:                                case '1':
                   2319:                                case '2':
                   2320:                                case '3':
                   2321:                                case '4':
                   2322:                                case '5':
                   2323:                                case '6':
                   2324:                                case '7':
                   2325:                                case '8':
                   2326:                                case '9':
                   2327:                                case ' ':
                   2328:                                case '-':
                   2329:                                case '.':
                   2330:                                        break;
                   2331:                                default :
                   2332:                                        str_flg = 0;
                   2333:                                        break;
                   2334:                                }
                   2335:                        }
                   2336: 
                   2337:                        if (str_flg) {
                   2338:                                convert_to_long_ex(zoffset);
                   2339:                                offset   = Z_LVAL_PP(zoffset);
                   2340:                        } else {
                   2341:                                enc_name     = enc_name2;
                   2342:                                enc_name_len = enc_name_len2;
                   2343:                        }
                   2344:                } else {
                   2345:                        convert_to_long_ex(zoffset);
                   2346:                        offset = Z_LVAL_PP(zoffset);
                   2347:                }
                   2348:        }
                   2349: 
                   2350:        if (enc_name != NULL) {
                   2351:                haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
                   2352:                if (haystack.no_encoding == mbfl_no_encoding_invalid) {
                   2353:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
                   2354:                        RETURN_FALSE;
                   2355:                }
                   2356:        }
                   2357: 
                   2358:        if (haystack.len <= 0) {
                   2359:                RETURN_FALSE;
                   2360:        }
                   2361:        if (needle.len <= 0) {
                   2362:                RETURN_FALSE;
                   2363:        }
                   2364: 
                   2365:        {
                   2366:                int haystack_char_len = mbfl_strlen(&haystack);
                   2367:                if ((offset > 0 && offset > haystack_char_len) ||
                   2368:                        (offset < 0 && -offset > haystack_char_len)) {
                   2369:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset is greater than the length of haystack string");
                   2370:                        RETURN_FALSE;
                   2371:                }
                   2372:        }
                   2373: 
                   2374:        n = mbfl_strpos(&haystack, &needle, offset, 1);
                   2375:        if (n >= 0) {
                   2376:                RETVAL_LONG(n);
                   2377:        } else {
                   2378:                RETVAL_FALSE;
                   2379:        }
                   2380: }
                   2381: /* }}} */
                   2382: 
                   2383: /* {{{ proto int mb_stripos(string haystack, string needle [, int offset [, string encoding]])
                   2384:    Finds position of first occurrence of a string within another, case insensitive */
                   2385: PHP_FUNCTION(mb_stripos)
                   2386: {
                   2387:        int n;
                   2388:        long offset;
                   2389:        mbfl_string haystack, needle;
1.1.1.2   misho    2390:        const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
1.1       misho    2391:        int from_encoding_len;
                   2392:        n = -1;
                   2393:        offset = 0;
                   2394: 
                   2395:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", (char **)&haystack.val, (int *)&haystack.len, (char **)&needle.val, (int *)&needle.len, &offset, &from_encoding, &from_encoding_len) == FAILURE) {
                   2396:                RETURN_FALSE;
                   2397:        }
                   2398:        if (needle.len == 0) {
                   2399:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
                   2400:                RETURN_FALSE;
                   2401:        }
                   2402:        n = php_mb_stripos(0, (char *)haystack.val, haystack.len, (char *)needle.val, needle.len, offset, from_encoding TSRMLS_CC);
                   2403: 
                   2404:        if (n >= 0) {
                   2405:                RETVAL_LONG(n);
                   2406:        } else {
                   2407:                RETVAL_FALSE;
                   2408:        }
                   2409: }
                   2410: /* }}} */
                   2411: 
                   2412: /* {{{ proto int mb_strripos(string haystack, string needle [, int offset [, string encoding]])
                   2413:    Finds position of last occurrence of a string within another, case insensitive */
                   2414: PHP_FUNCTION(mb_strripos)
                   2415: {
                   2416:        int n;
                   2417:        long offset;
                   2418:        mbfl_string haystack, needle;
1.1.1.2   misho    2419:        const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
1.1       misho    2420:        int from_encoding_len;
                   2421:        n = -1;
                   2422:        offset = 0;
                   2423: 
                   2424:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ls", (char **)&haystack.val, (int *)&haystack.len, (char **)&needle.val, (int *)&needle.len, &offset, &from_encoding, &from_encoding_len) == FAILURE) {
                   2425:                RETURN_FALSE;
                   2426:        }
                   2427: 
                   2428:        n = php_mb_stripos(1, (char *)haystack.val, haystack.len, (char *)needle.val, needle.len, offset, from_encoding TSRMLS_CC);
                   2429: 
                   2430:        if (n >= 0) {
                   2431:                RETVAL_LONG(n);
                   2432:        } else {
                   2433:                RETVAL_FALSE;
                   2434:        }
                   2435: }
                   2436: /* }}} */
                   2437: 
                   2438: /* {{{ proto string mb_strstr(string haystack, string needle[, bool part[, string encoding]])
                   2439:    Finds first occurrence of a string within another */
                   2440: PHP_FUNCTION(mb_strstr)
                   2441: {
                   2442:        int n, len, mblen;
                   2443:        mbfl_string haystack, needle, result, *ret = NULL;
                   2444:        char *enc_name = NULL;
                   2445:        int enc_name_len;
                   2446:        zend_bool part = 0;
                   2447: 
                   2448:        mbfl_string_init(&haystack);
                   2449:        mbfl_string_init(&needle);
                   2450:        haystack.no_language = MBSTRG(language);
1.1.1.2   misho    2451:        haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2452:        needle.no_language = MBSTRG(language);
1.1.1.2   misho    2453:        needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2454: 
                   2455:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|bs", (char **)&haystack.val, (int *)&haystack.len, (char **)&needle.val, (int *)&needle.len, &part, &enc_name, &enc_name_len) == FAILURE) {
                   2456:                RETURN_FALSE;
                   2457:        }
                   2458: 
                   2459:        if (enc_name != NULL) {
                   2460:                haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
                   2461:                if (haystack.no_encoding == mbfl_no_encoding_invalid) {
                   2462:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
                   2463:                        RETURN_FALSE;
                   2464:                }
                   2465:        }
                   2466: 
                   2467:        if (needle.len <= 0) {
                   2468:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
                   2469:                RETURN_FALSE;
                   2470:        }
                   2471:        n = mbfl_strpos(&haystack, &needle, 0, 0);
                   2472:        if (n >= 0) {
                   2473:                mblen = mbfl_strlen(&haystack);
                   2474:                if (part) {
                   2475:                        ret = mbfl_substr(&haystack, &result, 0, n);
                   2476:                        if (ret != NULL) {
                   2477:                                RETVAL_STRINGL((char *)ret->val, ret->len, 0);
                   2478:                        } else {
                   2479:                                RETVAL_FALSE;
                   2480:                        }
                   2481:                } else {
                   2482:                        len = (mblen - n);
                   2483:                        ret = mbfl_substr(&haystack, &result, n, len);
                   2484:                        if (ret != NULL) {
                   2485:                                RETVAL_STRINGL((char *)ret->val, ret->len, 0);
                   2486:                        } else {
                   2487:                                RETVAL_FALSE;
                   2488:                        }
                   2489:                }
                   2490:        } else {
                   2491:                RETVAL_FALSE;
                   2492:        }
                   2493: }
                   2494: /* }}} */
                   2495: 
                   2496: /* {{{ proto string mb_strrchr(string haystack, string needle[, bool part[, string encoding]])
                   2497:    Finds the last occurrence of a character in a string within another */
                   2498: PHP_FUNCTION(mb_strrchr)
                   2499: {
                   2500:        int n, len, mblen;
                   2501:        mbfl_string haystack, needle, result, *ret = NULL;
                   2502:        char *enc_name = NULL;
                   2503:        int enc_name_len;
                   2504:        zend_bool part = 0;
                   2505: 
                   2506:        mbfl_string_init(&haystack);
                   2507:        mbfl_string_init(&needle);
                   2508:        haystack.no_language = MBSTRG(language);
1.1.1.2   misho    2509:        haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2510:        needle.no_language = MBSTRG(language);
1.1.1.2   misho    2511:        needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2512: 
                   2513:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &enc_name, &enc_name_len) == FAILURE) {
                   2514:                RETURN_FALSE;
                   2515:        }
                   2516: 
                   2517:        if (enc_name != NULL) {
                   2518:                haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
                   2519:                if (haystack.no_encoding == mbfl_no_encoding_invalid) {
                   2520:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
                   2521:                        RETURN_FALSE;
                   2522:                }
                   2523:        }
                   2524: 
                   2525:        if (haystack.len <= 0) {
                   2526:                RETURN_FALSE;
                   2527:        }
                   2528:        if (needle.len <= 0) {
                   2529:                RETURN_FALSE;
                   2530:        }
                   2531:        n = mbfl_strpos(&haystack, &needle, 0, 1);
                   2532:        if (n >= 0) {
                   2533:                mblen = mbfl_strlen(&haystack);
                   2534:                if (part) {
                   2535:                        ret = mbfl_substr(&haystack, &result, 0, n);
                   2536:                        if (ret != NULL) {
                   2537:                                RETVAL_STRINGL((char *)ret->val, ret->len, 0);
                   2538:                        } else {
                   2539:                                RETVAL_FALSE;
                   2540:                        }
                   2541:                } else {
                   2542:                        len = (mblen - n);
                   2543:                        ret = mbfl_substr(&haystack, &result, n, len);
                   2544:                        if (ret != NULL) {
                   2545:                                RETVAL_STRINGL((char *)ret->val, ret->len, 0);
                   2546:                        } else {
                   2547:                                RETVAL_FALSE;
                   2548:                        }
                   2549:                }
                   2550:        } else {
                   2551:                RETVAL_FALSE;
                   2552:        }
                   2553: }
                   2554: /* }}} */
                   2555: 
                   2556: /* {{{ proto string mb_stristr(string haystack, string needle[, bool part[, string encoding]])
                   2557:    Finds first occurrence of a string within another, case insensitive */
                   2558: PHP_FUNCTION(mb_stristr)
                   2559: {
                   2560:        zend_bool part = 0;
                   2561:        unsigned int from_encoding_len, len, mblen;
                   2562:        int n;
                   2563:        mbfl_string haystack, needle, result, *ret = NULL;
1.1.1.2   misho    2564:        const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
1.1       misho    2565:        mbfl_string_init(&haystack);
                   2566:        mbfl_string_init(&needle);
                   2567:        haystack.no_language = MBSTRG(language);
1.1.1.2   misho    2568:        haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2569:        needle.no_language = MBSTRG(language);
1.1.1.2   misho    2570:        needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2571: 
                   2572: 
                   2573:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &from_encoding, &from_encoding_len) == FAILURE) {
                   2574:                RETURN_FALSE;
                   2575:        }
                   2576: 
                   2577:        if (!needle.len) {
                   2578:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
                   2579:                RETURN_FALSE;
                   2580:        }
                   2581: 
                   2582:        haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(from_encoding);
                   2583:        if (haystack.no_encoding == mbfl_no_encoding_invalid) {
                   2584:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", from_encoding);
                   2585:                RETURN_FALSE;
                   2586:        }
                   2587: 
                   2588:        n = php_mb_stripos(0, (char *)haystack.val, haystack.len, (char *)needle.val, needle.len, 0, from_encoding TSRMLS_CC);
                   2589: 
                   2590:        if (n <0) {
                   2591:                RETURN_FALSE;
                   2592:        }
                   2593: 
                   2594:        mblen = mbfl_strlen(&haystack);
                   2595: 
                   2596:        if (part) {
                   2597:                ret = mbfl_substr(&haystack, &result, 0, n);
                   2598:                if (ret != NULL) {
                   2599:                        RETVAL_STRINGL((char *)ret->val, ret->len, 0);
                   2600:                } else {
                   2601:                        RETVAL_FALSE;
                   2602:                }
                   2603:        } else {
                   2604:                len = (mblen - n);
                   2605:                ret = mbfl_substr(&haystack, &result, n, len);
                   2606:                if (ret != NULL) {
                   2607:                        RETVAL_STRINGL((char *)ret->val, ret->len, 0);
                   2608:                } else {
                   2609:                        RETVAL_FALSE;
                   2610:                }
                   2611:        }
                   2612: }
                   2613: /* }}} */
                   2614: 
                   2615: /* {{{ proto string mb_strrichr(string haystack, string needle[, bool part[, string encoding]])
                   2616:    Finds the last occurrence of a character in a string within another, case insensitive */
                   2617: PHP_FUNCTION(mb_strrichr)
                   2618: {
                   2619:        zend_bool part = 0;
                   2620:        int n, from_encoding_len, len, mblen;
                   2621:        mbfl_string haystack, needle, result, *ret = NULL;
1.1.1.2   misho    2622:        const char *from_encoding = MBSTRG(current_internal_encoding)->name;
1.1       misho    2623:        mbfl_string_init(&haystack);
                   2624:        mbfl_string_init(&needle);
                   2625:        haystack.no_language = MBSTRG(language);
1.1.1.2   misho    2626:        haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2627:        needle.no_language = MBSTRG(language);
1.1.1.2   misho    2628:        needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2629: 
                   2630: 
                   2631:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|bs", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &part, &from_encoding, &from_encoding_len) == FAILURE) {
                   2632:                RETURN_FALSE;
                   2633:        }
                   2634: 
                   2635:        haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(from_encoding);
                   2636:        if (haystack.no_encoding == mbfl_no_encoding_invalid) {
                   2637:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", from_encoding);
                   2638:                RETURN_FALSE;
                   2639:        }
                   2640: 
                   2641:        n = php_mb_stripos(1, (char *)haystack.val, haystack.len, (char *)needle.val, needle.len, 0, from_encoding TSRMLS_CC);
                   2642: 
                   2643:        if (n <0) {
                   2644:                RETURN_FALSE;
                   2645:        }
                   2646: 
                   2647:        mblen = mbfl_strlen(&haystack);
                   2648: 
                   2649:        if (part) {
                   2650:                ret = mbfl_substr(&haystack, &result, 0, n);
                   2651:                if (ret != NULL) {
                   2652:                        RETVAL_STRINGL((char *)ret->val, ret->len, 0);
                   2653:                } else {
                   2654:                        RETVAL_FALSE;
                   2655:                }
                   2656:        } else {
                   2657:                len = (mblen - n);
                   2658:                ret = mbfl_substr(&haystack, &result, n, len);
                   2659:                if (ret != NULL) {
                   2660:                        RETVAL_STRINGL((char *)ret->val, ret->len, 0);
                   2661:                } else {
                   2662:                        RETVAL_FALSE;
                   2663:                }
                   2664:        }
                   2665: }
                   2666: /* }}} */
                   2667: 
                   2668: /* {{{ proto int mb_substr_count(string haystack, string needle [, string encoding])
                   2669:    Count the number of substring occurrences */
                   2670: PHP_FUNCTION(mb_substr_count)
                   2671: {
                   2672:        int n;
                   2673:        mbfl_string haystack, needle;
                   2674:        char *enc_name = NULL;
                   2675:        int enc_name_len;
                   2676: 
                   2677:        mbfl_string_init(&haystack);
                   2678:        mbfl_string_init(&needle);
                   2679:        haystack.no_language = MBSTRG(language);
1.1.1.2   misho    2680:        haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2681:        needle.no_language = MBSTRG(language);
1.1.1.2   misho    2682:        needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2683: 
                   2684:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", (char **)&haystack.val, &haystack.len, (char **)&needle.val, &needle.len, &enc_name, &enc_name_len) == FAILURE) {
                   2685:                return;
                   2686:        }
                   2687: 
                   2688:        if (enc_name != NULL) {
                   2689:                haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
                   2690:                if (haystack.no_encoding == mbfl_no_encoding_invalid) {
                   2691:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
                   2692:                        RETURN_FALSE;
                   2693:                }
                   2694:        }
                   2695: 
                   2696:        if (needle.len <= 0) {
                   2697:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty substring");
                   2698:                RETURN_FALSE;
                   2699:        }
                   2700: 
                   2701:        n = mbfl_substr_count(&haystack, &needle);
                   2702:        if (n >= 0) {
                   2703:                RETVAL_LONG(n);
                   2704:        } else {
                   2705:                RETVAL_FALSE;
                   2706:        }
                   2707: }
                   2708: /* }}} */
                   2709: 
                   2710: /* {{{ proto string mb_substr(string str, int start [, int length [, string encoding]])
                   2711:    Returns part of a string */
                   2712: PHP_FUNCTION(mb_substr)
                   2713: {
                   2714:        size_t argc = ZEND_NUM_ARGS();
                   2715:        char *str, *encoding;
                   2716:        long from, len;
                   2717:        int mblen, str_len, encoding_len;
1.1.1.3 ! misho    2718:        zval **z_len = NULL;
1.1       misho    2719:        mbfl_string string, result, *ret;
                   2720: 
1.1.1.3 ! misho    2721:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|Zs", &str, &str_len, &from, &z_len, &encoding, &encoding_len) == FAILURE) {
1.1       misho    2722:                return;
                   2723:        }
                   2724: 
                   2725:        mbfl_string_init(&string);
                   2726:        string.no_language = MBSTRG(language);
1.1.1.2   misho    2727:        string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2728: 
                   2729:        if (argc == 4) {
                   2730:                string.no_encoding = mbfl_name2no_encoding(encoding);
                   2731:                if (string.no_encoding == mbfl_no_encoding_invalid) {
                   2732:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encoding);
                   2733:                        RETURN_FALSE;
                   2734:                }
                   2735:        }
                   2736: 
                   2737:        string.val = (unsigned char *)str;
                   2738:        string.len = str_len;
                   2739: 
1.1.1.3 ! misho    2740:        if (argc < 3 || Z_TYPE_PP(z_len) == IS_NULL) {
1.1       misho    2741:                len = str_len;
1.1.1.3 ! misho    2742:        } else {
        !          2743:                convert_to_long_ex(z_len);
        !          2744:                len = Z_LVAL_PP(z_len);
1.1       misho    2745:        }
                   2746: 
                   2747:        /* measures length */
                   2748:        mblen = 0;
                   2749:        if (from < 0 || len < 0) {
                   2750:                mblen = mbfl_strlen(&string);
                   2751:        }
                   2752: 
                   2753:        /* if "from" position is negative, count start position from the end
                   2754:         * of the string
                   2755:         */
                   2756:        if (from < 0) {
                   2757:                from = mblen + from;
                   2758:                if (from < 0) {
                   2759:                        from = 0;
                   2760:                }
                   2761:        }
                   2762: 
                   2763:        /* if "length" position is negative, set it to the length
                   2764:         * needed to stop that many chars from the end of the string
                   2765:         */
                   2766:        if (len < 0) {
                   2767:                len = (mblen - from) + len;
                   2768:                if (len < 0) {
                   2769:                        len = 0;
                   2770:                }
                   2771:        }
                   2772: 
                   2773:        if (((MBSTRG(func_overload) & MB_OVERLOAD_STRING) == MB_OVERLOAD_STRING)
                   2774:                && (from >= mbfl_strlen(&string))) {
                   2775:                RETURN_FALSE;
                   2776:        }
                   2777: 
                   2778:        ret = mbfl_substr(&string, &result, from, len);
                   2779:        if (NULL == ret) {
                   2780:                RETURN_FALSE;
                   2781:        }
                   2782: 
                   2783:        RETURN_STRINGL((char *)ret->val, ret->len, 0); /* the string is already strdup()'ed */
                   2784: }
                   2785: /* }}} */
                   2786: 
                   2787: /* {{{ proto string mb_strcut(string str, int start [, int length [, string encoding]])
                   2788:    Returns part of a string */
                   2789: PHP_FUNCTION(mb_strcut)
                   2790: {
                   2791:        size_t argc = ZEND_NUM_ARGS();
                   2792:        char *encoding;
                   2793:        long from, len;
                   2794:        int encoding_len;
1.1.1.3 ! misho    2795:        zval **z_len = NULL;
1.1       misho    2796:        mbfl_string string, result, *ret;
                   2797: 
                   2798:        mbfl_string_init(&string);
                   2799:        string.no_language = MBSTRG(language);
1.1.1.2   misho    2800:        string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2801: 
1.1.1.3 ! misho    2802:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|Zs", (char **)&string.val, (int **)&string.len, &from, &z_len, &encoding, &encoding_len) == FAILURE) {
1.1       misho    2803:                return;
                   2804:        }
                   2805: 
                   2806:        if (argc == 4) {
                   2807:                string.no_encoding = mbfl_name2no_encoding(encoding);
                   2808:                if (string.no_encoding == mbfl_no_encoding_invalid) {
                   2809:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encoding);
                   2810:                        RETURN_FALSE;
                   2811:                }
                   2812:        }
                   2813: 
1.1.1.3 ! misho    2814:        if (argc < 3 || Z_TYPE_PP(z_len) == IS_NULL) {
1.1       misho    2815:                len = string.len;
1.1.1.3 ! misho    2816:        } else {
        !          2817:                convert_to_long_ex(z_len);
        !          2818:                len = Z_LVAL_PP(z_len);
1.1       misho    2819:        }
                   2820: 
                   2821:        /* if "from" position is negative, count start position from the end
                   2822:         * of the string
                   2823:         */
                   2824:        if (from < 0) {
                   2825:                from = string.len + from;
                   2826:                if (from < 0) {
                   2827:                        from = 0;
                   2828:                }
                   2829:        }
                   2830: 
                   2831:        /* if "length" position is negative, set it to the length
                   2832:         * needed to stop that many chars from the end of the string
                   2833:         */
                   2834:        if (len < 0) {
                   2835:                len = (string.len - from) + len;
                   2836:                if (len < 0) {
                   2837:                        len = 0;
                   2838:                }
                   2839:        }
                   2840: 
                   2841:        if ((unsigned int)from > string.len) {
                   2842:                RETURN_FALSE;
                   2843:        }
                   2844: 
                   2845:        ret = mbfl_strcut(&string, &result, from, len);
                   2846:        if (ret == NULL) {
                   2847:                RETURN_FALSE;
                   2848:        }
                   2849: 
                   2850:        RETURN_STRINGL((char *)ret->val, ret->len, 0); /* the string is already strdup()'ed */
                   2851: }
                   2852: /* }}} */
                   2853: 
                   2854: /* {{{ proto int mb_strwidth(string str [, string encoding])
                   2855:    Gets terminal width of a string */
                   2856: PHP_FUNCTION(mb_strwidth)
                   2857: {
                   2858:        int n;
                   2859:        mbfl_string string;
                   2860:        char *enc_name = NULL;
                   2861:        int enc_name_len;
                   2862: 
                   2863:        mbfl_string_init(&string);
                   2864: 
                   2865:        string.no_language = MBSTRG(language);
1.1.1.2   misho    2866:        string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2867: 
                   2868:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", (char **)&string.val, &string.len, &enc_name, &enc_name_len) == FAILURE) {
                   2869:                return;
                   2870:        }
                   2871: 
                   2872:        if (enc_name != NULL) {
                   2873:                string.no_encoding = mbfl_name2no_encoding(enc_name);
                   2874:                if (string.no_encoding == mbfl_no_encoding_invalid) {
                   2875:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
                   2876:                        RETURN_FALSE;
                   2877:                }
                   2878:        }
                   2879: 
                   2880:        n = mbfl_strwidth(&string);
                   2881:        if (n >= 0) {
                   2882:                RETVAL_LONG(n);
                   2883:        } else {
                   2884:                RETVAL_FALSE;
                   2885:        }
                   2886: }
                   2887: /* }}} */
                   2888: 
                   2889: /* {{{ proto string mb_strimwidth(string str, int start, int width [, string trimmarker [, string encoding]])
                   2890:    Trim the string in terminal width */
                   2891: PHP_FUNCTION(mb_strimwidth)
                   2892: {
                   2893:        char *str, *trimmarker, *encoding;
                   2894:        long from, width;
                   2895:        int str_len, trimmarker_len, encoding_len;
                   2896:        mbfl_string string, result, marker, *ret;
                   2897: 
                   2898:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll|ss", &str, &str_len, &from, &width, &trimmarker, &trimmarker_len, &encoding, &encoding_len) == FAILURE) {
                   2899:                return;
                   2900:        }
                   2901: 
                   2902:        mbfl_string_init(&string);
                   2903:        mbfl_string_init(&marker);
                   2904:        string.no_language = MBSTRG(language);
1.1.1.2   misho    2905:        string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2906:        marker.no_language = MBSTRG(language);
1.1.1.2   misho    2907:        marker.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    2908:        marker.val = NULL;
                   2909:        marker.len = 0;
                   2910: 
                   2911:        if (ZEND_NUM_ARGS() == 5) {
                   2912:                string.no_encoding = marker.no_encoding = mbfl_name2no_encoding(encoding);
                   2913:                if (string.no_encoding == mbfl_no_encoding_invalid) {
                   2914:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encoding);
                   2915:                        RETURN_FALSE;
                   2916:                }
                   2917:        }
                   2918: 
                   2919:        string.val = (unsigned char *)str;
                   2920:        string.len = str_len;
                   2921: 
                   2922:        if (from < 0 || from > str_len) {
                   2923:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Start position is out of range");
                   2924:                RETURN_FALSE;
                   2925:        }
                   2926: 
                   2927:        if (width < 0) {
                   2928:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width is negative value");
                   2929:                RETURN_FALSE;
                   2930:        }
                   2931: 
                   2932:        if (ZEND_NUM_ARGS() >= 4) {
                   2933:                marker.val = (unsigned char *)trimmarker;
                   2934:                marker.len = trimmarker_len;
                   2935:        }
                   2936: 
                   2937:        ret = mbfl_strimwidth(&string, &marker, &result, from, width);
                   2938: 
                   2939:        if (ret == NULL) {
                   2940:                RETURN_FALSE;
                   2941:        }
                   2942: 
                   2943:        RETVAL_STRINGL((char *)ret->val, ret->len, 0); /* the string is already strdup()'ed */
                   2944: }
                   2945: /* }}} */
                   2946: 
                   2947: /* {{{ MBSTRING_API char *php_mb_convert_encoding() */
                   2948: MBSTRING_API char * php_mb_convert_encoding(const char *input, size_t length, const char *_to_encoding, const char *_from_encodings, size_t *output_len TSRMLS_DC)
                   2949: {
                   2950:        mbfl_string string, result, *ret;
1.1.1.2   misho    2951:        const mbfl_encoding *from_encoding, *to_encoding;
1.1       misho    2952:        mbfl_buffer_converter *convd;
1.1.1.2   misho    2953:        size_t size;
                   2954:        const mbfl_encoding **list;
1.1       misho    2955:        char *output=NULL;
                   2956: 
                   2957:        if (output_len) {
                   2958:                *output_len = 0;
                   2959:        }
                   2960:        if (!input) {
                   2961:                return NULL;
                   2962:        }
                   2963:        /* new encoding */
                   2964:        if (_to_encoding && strlen(_to_encoding)) {
1.1.1.2   misho    2965:                to_encoding = mbfl_name2encoding(_to_encoding);
                   2966:                if (!to_encoding) {
1.1       misho    2967:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", _to_encoding);
                   2968:                        return NULL;
                   2969:                }
                   2970:        } else {
                   2971:                to_encoding = MBSTRG(current_internal_encoding);
                   2972:        }
                   2973: 
                   2974:        /* initialize string */
                   2975:        mbfl_string_init(&string);
                   2976:        mbfl_string_init(&result);
                   2977:        from_encoding = MBSTRG(current_internal_encoding);
1.1.1.2   misho    2978:        string.no_encoding = from_encoding->no_encoding;
1.1       misho    2979:        string.no_language = MBSTRG(language);
                   2980:        string.val = (unsigned char *)input;
                   2981:        string.len = length;
                   2982: 
                   2983:        /* pre-conversion encoding */
                   2984:        if (_from_encodings) {
                   2985:                list = NULL;
                   2986:                size = 0;
1.1.1.2   misho    2987:                php_mb_parse_encoding_list(_from_encodings, strlen(_from_encodings), &list, &size, 0 TSRMLS_CC);
1.1       misho    2988:                if (size == 1) {
                   2989:                        from_encoding = *list;
1.1.1.2   misho    2990:                        string.no_encoding = from_encoding->no_encoding;
1.1       misho    2991:                } else if (size > 1) {
                   2992:                        /* auto detect */
1.1.1.2   misho    2993:                        from_encoding = mbfl_identify_encoding2(&string, list, size, MBSTRG(strict_detection));
                   2994:                        if (from_encoding) {
                   2995:                                string.no_encoding = from_encoding->no_encoding;
1.1       misho    2996:                        } else {
                   2997:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to detect character encoding");
1.1.1.2   misho    2998:                                from_encoding = &mbfl_encoding_pass;
1.1       misho    2999:                                to_encoding = from_encoding;
1.1.1.2   misho    3000:                                string.no_encoding = from_encoding->no_encoding;
1.1       misho    3001:                        }
                   3002:                } else {
                   3003:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal character encoding specified");
                   3004:                }
                   3005:                if (list != NULL) {
                   3006:                        efree((void *)list);
                   3007:                }
                   3008:        }
                   3009: 
                   3010:        /* initialize converter */
1.1.1.2   misho    3011:        convd = mbfl_buffer_converter_new2(from_encoding, to_encoding, string.len);
1.1       misho    3012:        if (convd == NULL) {
                   3013:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create character encoding converter");
                   3014:                return NULL;
                   3015:        }
                   3016:        mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
                   3017:        mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
                   3018: 
                   3019:        /* do it */
                   3020:        ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
                   3021:        if (ret) {
                   3022:                if (output_len) {
                   3023:                        *output_len = ret->len;
                   3024:                }
                   3025:                output = (char *)ret->val;
                   3026:        }
                   3027: 
                   3028:        MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
                   3029:        mbfl_buffer_converter_delete(convd);
                   3030:        return output;
                   3031: }
                   3032: /* }}} */
                   3033: 
                   3034: /* {{{ proto string mb_convert_encoding(string str, string to-encoding [, mixed from-encoding])
                   3035:    Returns converted string in desired encoding */
                   3036: PHP_FUNCTION(mb_convert_encoding)
                   3037: {
                   3038:        char *arg_str, *arg_new;
                   3039:        int str_len, new_len;
                   3040:        zval *arg_old;
                   3041:        int i;
                   3042:        size_t size, l, n;
                   3043:        char *_from_encodings = NULL, *ret, *s_free = NULL;
                   3044: 
                   3045:        zval **hash_entry;
                   3046:        HashTable *target_hash;
                   3047: 
                   3048:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|z", &arg_str, &str_len, &arg_new, &new_len, &arg_old) == FAILURE) {
                   3049:                return;
                   3050:        }
                   3051: 
                   3052:        if (ZEND_NUM_ARGS() == 3) {
                   3053:                switch (Z_TYPE_P(arg_old)) {
                   3054:                case IS_ARRAY:
                   3055:                        target_hash = Z_ARRVAL_P(arg_old);
                   3056:                        zend_hash_internal_pointer_reset(target_hash);
                   3057:                        i = zend_hash_num_elements(target_hash);
                   3058:                        _from_encodings = NULL;
                   3059: 
                   3060:                        while (i > 0) {
                   3061:                                if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) {
                   3062:                                        break;
                   3063:                                }
                   3064: 
                   3065:                                convert_to_string_ex(hash_entry);
                   3066: 
                   3067:                                if ( _from_encodings) {
                   3068:                                        l = strlen(_from_encodings);
                   3069:                                        n = strlen(Z_STRVAL_PP(hash_entry));
                   3070:                                        _from_encodings = erealloc(_from_encodings, l+n+2);
                   3071:                                        strcpy(_from_encodings+l, ",");
                   3072:                                        strcpy(_from_encodings+l+1, Z_STRVAL_PP(hash_entry));
                   3073:                                } else {
                   3074:                                        _from_encodings = estrdup(Z_STRVAL_PP(hash_entry));
                   3075:                                }
                   3076: 
                   3077:                                zend_hash_move_forward(target_hash);
                   3078:                                i--;
                   3079:                        }
                   3080: 
                   3081:                        if (_from_encodings != NULL && !strlen(_from_encodings)) {
                   3082:                                efree(_from_encodings);
                   3083:                                _from_encodings = NULL;
                   3084:                        }
                   3085:                        s_free = _from_encodings;
                   3086:                        break;
                   3087:                default:
                   3088:                        convert_to_string(arg_old);
                   3089:                        _from_encodings = Z_STRVAL_P(arg_old);
                   3090:                        break;
                   3091:                }
                   3092:        }
                   3093: 
                   3094:        /* new encoding */
                   3095:        ret = php_mb_convert_encoding(arg_str, str_len, arg_new, _from_encodings, &size TSRMLS_CC);
                   3096:        if (ret != NULL) {
                   3097:                RETVAL_STRINGL(ret, size, 0);           /* the string is already strdup()'ed */
                   3098:        } else {
                   3099:                RETVAL_FALSE;
                   3100:        }
                   3101: 
                   3102:        if ( s_free) {
                   3103:                efree(s_free);
                   3104:        }
                   3105: }
                   3106: /* }}} */
                   3107: 
                   3108: /* {{{ proto string mb_convert_case(string sourcestring, int mode [, string encoding])
                   3109:    Returns a case-folded version of sourcestring */
                   3110: PHP_FUNCTION(mb_convert_case)
                   3111: {
1.1.1.2   misho    3112:        const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
                   3113:        char *str;
1.1       misho    3114:        int str_len, from_encoding_len;
                   3115:        long case_mode = 0;
                   3116:        char *newstr;
                   3117:        size_t ret_len;
                   3118: 
                   3119:        RETVAL_FALSE;
                   3120:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|s!", &str, &str_len,
                   3121:                                &case_mode, &from_encoding, &from_encoding_len) == FAILURE)
                   3122:                RETURN_FALSE;
                   3123: 
                   3124:        newstr = php_unicode_convert_case(case_mode, str, (size_t) str_len, &ret_len, from_encoding TSRMLS_CC);
                   3125: 
                   3126:        if (newstr) {
                   3127:                RETVAL_STRINGL(newstr, ret_len, 0);
                   3128:        }       
                   3129: }
                   3130: /* }}} */
                   3131: 
                   3132: /* {{{ proto string mb_strtoupper(string sourcestring [, string encoding])
                   3133:  *  Returns a uppercased version of sourcestring
                   3134:  */
                   3135: PHP_FUNCTION(mb_strtoupper)
                   3136: {
1.1.1.2   misho    3137:        const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
                   3138:        char *str;
1.1       misho    3139:        int str_len, from_encoding_len;
                   3140:        char *newstr;
                   3141:        size_t ret_len;
                   3142: 
                   3143:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &str, &str_len,
                   3144:                                &from_encoding, &from_encoding_len) == FAILURE) {
                   3145:                return;
                   3146:        }
                   3147:        newstr = php_unicode_convert_case(PHP_UNICODE_CASE_UPPER, str, (size_t) str_len, &ret_len, from_encoding TSRMLS_CC);
                   3148: 
                   3149:        if (newstr) {
                   3150:                RETURN_STRINGL(newstr, ret_len, 0);
                   3151:        }
                   3152:        RETURN_FALSE;
                   3153: }
                   3154: /* }}} */
                   3155: 
                   3156: /* {{{ proto string mb_strtolower(string sourcestring [, string encoding])
                   3157:  *  Returns a lowercased version of sourcestring
                   3158:  */
                   3159: PHP_FUNCTION(mb_strtolower)
                   3160: {
1.1.1.2   misho    3161:        const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
                   3162:        char *str;
1.1       misho    3163:        int str_len, from_encoding_len;
                   3164:        char *newstr;
                   3165:        size_t ret_len;
                   3166: 
                   3167:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &str, &str_len,
                   3168:                                &from_encoding, &from_encoding_len) == FAILURE) {
                   3169:                return;
                   3170:        }
                   3171:        newstr = php_unicode_convert_case(PHP_UNICODE_CASE_LOWER, str, (size_t) str_len, &ret_len, from_encoding TSRMLS_CC);
                   3172: 
                   3173:        if (newstr) {
                   3174:                RETURN_STRINGL(newstr, ret_len, 0);
                   3175:        }
                   3176:        RETURN_FALSE;
                   3177: }
                   3178: /* }}} */
                   3179: 
                   3180: /* {{{ proto string mb_detect_encoding(string str [, mixed encoding_list [, bool strict]])
                   3181:    Encodings of the given string is returned (as a string) */
                   3182: PHP_FUNCTION(mb_detect_encoding)
                   3183: {
                   3184:        char *str;
                   3185:        int str_len;
                   3186:        zend_bool strict=0;
                   3187:        zval *encoding_list;
                   3188: 
                   3189:        mbfl_string string;
1.1.1.2   misho    3190:        const mbfl_encoding *ret;
                   3191:        const mbfl_encoding **elist, **list;
                   3192:        size_t size;
1.1       misho    3193: 
                   3194:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zb", &str, &str_len, &encoding_list, &strict) == FAILURE) {
                   3195:                return;
                   3196:        }
                   3197: 
                   3198:        /* make encoding list */
                   3199:        list = NULL;
                   3200:        size = 0;
                   3201:        if (ZEND_NUM_ARGS() >= 2 && !ZVAL_IS_NULL(encoding_list)) {
                   3202:                switch (Z_TYPE_P(encoding_list)) {
                   3203:                case IS_ARRAY:
1.1.1.2   misho    3204:                        if (FAILURE == php_mb_parse_encoding_array(encoding_list, &list, &size, 0 TSRMLS_CC)) {
1.1       misho    3205:                                if (list) {
                   3206:                                        efree(list);
                   3207:                                        list = NULL;
                   3208:                                        size = 0;
                   3209:                                }
                   3210:                        }
                   3211:                        break;
                   3212:                default:
                   3213:                        convert_to_string(encoding_list);
1.1.1.2   misho    3214:                        if (FAILURE == php_mb_parse_encoding_list(Z_STRVAL_P(encoding_list), Z_STRLEN_P(encoding_list), &list, &size, 0 TSRMLS_CC)) {
1.1       misho    3215:                                if (list) {
                   3216:                                        efree(list);
                   3217:                                        list = NULL;
                   3218:                                        size = 0;
                   3219:                                }
                   3220:                        }
                   3221:                        break;
                   3222:                }
                   3223:                if (size <= 0) {
                   3224:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal argument");
                   3225:                }
                   3226:        }
                   3227: 
                   3228:        if (ZEND_NUM_ARGS() < 3) {
                   3229:                strict = (zend_bool)MBSTRG(strict_detection);
                   3230:        }
                   3231: 
                   3232:        if (size > 0 && list != NULL) {
                   3233:                elist = list;
                   3234:        } else {
                   3235:                elist = MBSTRG(current_detect_order_list);
                   3236:                size = MBSTRG(current_detect_order_list_size);
                   3237:        }
                   3238: 
                   3239:        mbfl_string_init(&string);
                   3240:        string.no_language = MBSTRG(language);
                   3241:        string.val = (unsigned char *)str;
                   3242:        string.len = str_len;
1.1.1.2   misho    3243:        ret = mbfl_identify_encoding2(&string, elist, size, strict);
1.1       misho    3244: 
                   3245:        if (list != NULL) {
                   3246:                efree((void *)list);
                   3247:        }
                   3248: 
                   3249:        if (ret == NULL) {
                   3250:                RETURN_FALSE;
                   3251:        }
                   3252: 
1.1.1.2   misho    3253:        RETVAL_STRING((char *)ret->name, 1);
1.1       misho    3254: }
                   3255: /* }}} */
                   3256: 
                   3257: /* {{{ proto mixed mb_list_encodings()
                   3258:    Returns an array of all supported entity encodings */
                   3259: PHP_FUNCTION(mb_list_encodings)
                   3260: {
                   3261:        const mbfl_encoding **encodings;
                   3262:        const mbfl_encoding *encoding;
                   3263:        int i;
                   3264: 
                   3265:        array_init(return_value);
                   3266:        i = 0;
                   3267:        encodings = mbfl_get_supported_encodings();
                   3268:        while ((encoding = encodings[i++]) != NULL) {
                   3269:                add_next_index_string(return_value, (char *) encoding->name, 1);
                   3270:        }
                   3271: }
                   3272: /* }}} */
                   3273: 
                   3274: /* {{{ proto array mb_encoding_aliases(string encoding)
                   3275:    Returns an array of the aliases of a given encoding name */
                   3276: PHP_FUNCTION(mb_encoding_aliases)
                   3277: {
                   3278:        const mbfl_encoding *encoding;
                   3279:        char *name = NULL;
                   3280:        int name_len;
                   3281: 
                   3282:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
                   3283:                RETURN_FALSE;
                   3284:        }
                   3285: 
                   3286:        encoding = mbfl_name2encoding(name);
                   3287:        if (!encoding) {
                   3288:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
                   3289:                RETURN_FALSE;
                   3290:        }
                   3291: 
                   3292:        array_init(return_value);
                   3293:        if (encoding->aliases != NULL) {
                   3294:                const char **alias;
                   3295:                for (alias = *encoding->aliases; *alias; ++alias) {
                   3296:                        add_next_index_string(return_value, (char *)*alias, 1);
                   3297:                }
                   3298:        }
                   3299: }
                   3300: /* }}} */
                   3301: 
                   3302: /* {{{ proto string mb_encode_mimeheader(string str [, string charset [, string transfer-encoding [, string linefeed [, int indent]]]])
                   3303:    Converts the string to MIME "encoded-word" in the format of =?charset?(B|Q)?encoded_string?= */
                   3304: PHP_FUNCTION(mb_encode_mimeheader)
                   3305: {
                   3306:        enum mbfl_no_encoding charset, transenc;
                   3307:        mbfl_string  string, result, *ret;
                   3308:        char *charset_name = NULL;
                   3309:        int charset_name_len;
                   3310:        char *trans_enc_name = NULL;
                   3311:        int trans_enc_name_len;
                   3312:        char *linefeed = "\r\n";
                   3313:        int linefeed_len;
                   3314:        long indent = 0;
                   3315: 
                   3316:        mbfl_string_init(&string);
                   3317:        string.no_language = MBSTRG(language);
1.1.1.2   misho    3318:        string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    3319: 
                   3320:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sssl", (char **)&string.val, &string.len, &charset_name, &charset_name_len, &trans_enc_name, &trans_enc_name_len, &linefeed, &linefeed_len, &indent) == FAILURE) {
                   3321:                return;
                   3322:        }
                   3323: 
                   3324:        charset = mbfl_no_encoding_pass;
                   3325:        transenc = mbfl_no_encoding_base64;
                   3326: 
                   3327:        if (charset_name != NULL) {
                   3328:                charset = mbfl_name2no_encoding(charset_name);
                   3329:                if (charset == mbfl_no_encoding_invalid) {
                   3330:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", charset_name);
                   3331:                        RETURN_FALSE;
                   3332:                }
                   3333:        } else {
                   3334:                const mbfl_language *lang = mbfl_no2language(MBSTRG(language));
                   3335:                if (lang != NULL) {
                   3336:                        charset = lang->mail_charset;
                   3337:                        transenc = lang->mail_header_encoding;
                   3338:                }
                   3339:        }
                   3340: 
                   3341:        if (trans_enc_name != NULL) {
                   3342:                if (*trans_enc_name == 'B' || *trans_enc_name == 'b') {
                   3343:                        transenc = mbfl_no_encoding_base64;
                   3344:                } else if (*trans_enc_name == 'Q' || *trans_enc_name == 'q') {
                   3345:                        transenc = mbfl_no_encoding_qprint;
                   3346:                }
                   3347:        }
                   3348: 
                   3349:        mbfl_string_init(&result);
                   3350:        ret = mbfl_mime_header_encode(&string, &result, charset, transenc, linefeed, indent);
                   3351:        if (ret != NULL) {
1.1.1.2   misho    3352:                RETVAL_STRINGL((char *)ret->val, ret->len, 0);  /* the string is already strdup()'ed */
1.1       misho    3353:        } else {
                   3354:                RETVAL_FALSE;
                   3355:        }
                   3356: }
                   3357: /* }}} */
                   3358: 
                   3359: /* {{{ proto string mb_decode_mimeheader(string string)
                   3360:    Decodes the MIME "encoded-word" in the string */
                   3361: PHP_FUNCTION(mb_decode_mimeheader)
                   3362: {
                   3363:        mbfl_string string, result, *ret;
                   3364: 
                   3365:        mbfl_string_init(&string);
                   3366:        string.no_language = MBSTRG(language);
1.1.1.2   misho    3367:        string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    3368: 
                   3369:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", (char **)&string.val, &string.len) == FAILURE) {
                   3370:                return;
                   3371:        }
                   3372: 
                   3373:        mbfl_string_init(&result);
1.1.1.2   misho    3374:        ret = mbfl_mime_header_decode(&string, &result, MBSTRG(current_internal_encoding)->no_encoding);
1.1       misho    3375:        if (ret != NULL) {
1.1.1.2   misho    3376:                RETVAL_STRINGL((char *)ret->val, ret->len, 0);  /* the string is already strdup()'ed */
1.1       misho    3377:        } else {
                   3378:                RETVAL_FALSE;
                   3379:        }
                   3380: }
                   3381: /* }}} */
                   3382: 
                   3383: /* {{{ proto string mb_convert_kana(string str [, string option] [, string encoding])
                   3384:    Conversion between full-width character and half-width character (Japanese) */
                   3385: PHP_FUNCTION(mb_convert_kana)
                   3386: {
                   3387:        int opt, i;
                   3388:        mbfl_string string, result, *ret;
                   3389:        char *optstr = NULL;
                   3390:        int optstr_len;
                   3391:        char *encname = NULL;
                   3392:        int encname_len;
                   3393: 
                   3394:        mbfl_string_init(&string);
                   3395:        string.no_language = MBSTRG(language);
1.1.1.2   misho    3396:        string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    3397: 
                   3398:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ss", (char **)&string.val, &string.len, &optstr, &optstr_len, &encname, &encname_len) == FAILURE) {
                   3399:                return;
                   3400:        }
                   3401: 
                   3402:        /* option */
                   3403:        if (optstr != NULL) {
                   3404:                char *p = optstr;
                   3405:                int n = optstr_len;
                   3406:                i = 0;
                   3407:                opt = 0;
                   3408:                while (i < n) {
                   3409:                        i++;
                   3410:                        switch (*p++) {
                   3411:                        case 'A':
                   3412:                                opt |= 0x1;
                   3413:                                break;
                   3414:                        case 'a':
                   3415:                                opt |= 0x10;
                   3416:                                break;
                   3417:                        case 'R':
                   3418:                                opt |= 0x2;
                   3419:                                break;
                   3420:                        case 'r':
                   3421:                                opt |= 0x20;
                   3422:                                break;
                   3423:                        case 'N':
                   3424:                                opt |= 0x4;
                   3425:                                break;
                   3426:                        case 'n':
                   3427:                                opt |= 0x40;
                   3428:                                break;
                   3429:                        case 'S':
                   3430:                                opt |= 0x8;
                   3431:                                break;
                   3432:                        case 's':
                   3433:                                opt |= 0x80;
                   3434:                                break;
                   3435:                        case 'K':
                   3436:                                opt |= 0x100;
                   3437:                                break;
                   3438:                        case 'k':
                   3439:                                opt |= 0x1000;
                   3440:                                break;
                   3441:                        case 'H':
                   3442:                                opt |= 0x200;
                   3443:                                break;
                   3444:                        case 'h':
                   3445:                                opt |= 0x2000;
                   3446:                                break;
                   3447:                        case 'V':
                   3448:                                opt |= 0x800;
                   3449:                                break;
                   3450:                        case 'C':
                   3451:                                opt |= 0x10000;
                   3452:                                break;
                   3453:                        case 'c':
                   3454:                                opt |= 0x20000;
                   3455:                                break;
                   3456:                        case 'M':
                   3457:                                opt |= 0x100000;
                   3458:                                break;
                   3459:                        case 'm':
                   3460:                                opt |= 0x200000;
                   3461:                                break;
                   3462:                        }
                   3463:                }
                   3464:        } else {
                   3465:                opt = 0x900;
                   3466:        }
                   3467: 
                   3468:        /* encoding */
                   3469:        if (encname != NULL) {
                   3470:                string.no_encoding = mbfl_name2no_encoding(encname);
                   3471:                if (string.no_encoding == mbfl_no_encoding_invalid) {
                   3472:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encname);
                   3473:                        RETURN_FALSE;
                   3474:                }
                   3475:        }
                   3476: 
                   3477:        ret = mbfl_ja_jp_hantozen(&string, &result, opt);
                   3478:        if (ret != NULL) {
                   3479:                RETVAL_STRINGL((char *)ret->val, ret->len, 0);          /* the string is already strdup()'ed */
                   3480:        } else {
                   3481:                RETVAL_FALSE;
                   3482:        }
                   3483: }
                   3484: /* }}} */
                   3485: 
                   3486: #define PHP_MBSTR_STACK_BLOCK_SIZE 32
                   3487: 
                   3488: /* {{{ proto string mb_convert_variables(string to-encoding, mixed from-encoding, mixed vars [, ...])
                   3489:    Converts the string resource in variables to desired encoding */
                   3490: PHP_FUNCTION(mb_convert_variables)
                   3491: {
                   3492:        zval ***args, ***stack, **var, **hash_entry, **zfrom_enc;
                   3493:        HashTable *target_hash;
                   3494:        mbfl_string string, result, *ret;
1.1.1.2   misho    3495:        const mbfl_encoding *from_encoding, *to_encoding;
1.1       misho    3496:        mbfl_encoding_detector *identd;
                   3497:        mbfl_buffer_converter *convd;
1.1.1.2   misho    3498:        int n, to_enc_len, argc, stack_level, stack_max;
                   3499:        size_t elistsz;
                   3500:        const mbfl_encoding **elist;
                   3501:        char *to_enc;
1.1       misho    3502:        void *ptmp;     
1.1.1.2   misho    3503: 
1.1       misho    3504:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sZ+", &to_enc, &to_enc_len, &zfrom_enc, &args, &argc) == FAILURE) {
                   3505:                return;
                   3506:        }
                   3507: 
                   3508:        /* new encoding */
1.1.1.2   misho    3509:        to_encoding = mbfl_name2encoding(to_enc);
                   3510:        if (!to_encoding) {
1.1       misho    3511:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", to_enc);
                   3512:                efree(args);
                   3513:                RETURN_FALSE;
                   3514:        }
                   3515: 
                   3516:        /* initialize string */
                   3517:        mbfl_string_init(&string);
                   3518:        mbfl_string_init(&result);
                   3519:        from_encoding = MBSTRG(current_internal_encoding);
1.1.1.2   misho    3520:        string.no_encoding = from_encoding->no_encoding;
1.1       misho    3521:        string.no_language = MBSTRG(language);
                   3522: 
                   3523:        /* pre-conversion encoding */
                   3524:        elist = NULL;
                   3525:        elistsz = 0;
                   3526:        switch (Z_TYPE_PP(zfrom_enc)) {
                   3527:        case IS_ARRAY:
                   3528:                php_mb_parse_encoding_array(*zfrom_enc, &elist, &elistsz, 0 TSRMLS_CC);
                   3529:                break;
                   3530:        default:
                   3531:                convert_to_string_ex(zfrom_enc);
                   3532:                php_mb_parse_encoding_list(Z_STRVAL_PP(zfrom_enc), Z_STRLEN_PP(zfrom_enc), &elist, &elistsz, 0 TSRMLS_CC);
                   3533:                break;
                   3534:        }
                   3535:        if (elistsz <= 0) {
1.1.1.2   misho    3536:                from_encoding = &mbfl_encoding_pass;
1.1       misho    3537:        } else if (elistsz == 1) {
                   3538:                from_encoding = *elist;
                   3539:        } else {
                   3540:                /* auto detect */
1.1.1.2   misho    3541:                from_encoding = NULL;
1.1       misho    3542:                stack_max = PHP_MBSTR_STACK_BLOCK_SIZE;
                   3543:                stack = (zval ***)safe_emalloc(stack_max, sizeof(zval **), 0);
                   3544:                stack_level = 0;
1.1.1.2   misho    3545:                identd = mbfl_encoding_detector_new2(elist, elistsz, MBSTRG(strict_detection));
1.1       misho    3546:                if (identd != NULL) {
                   3547:                        n = 0;
                   3548:                        while (n < argc || stack_level > 0) {
                   3549:                                if (stack_level <= 0) {
                   3550:                                        var = args[n++];
                   3551:                                        if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
                   3552:                                                target_hash = HASH_OF(*var);
                   3553:                                                if (target_hash != NULL) {
                   3554:                                                        zend_hash_internal_pointer_reset(target_hash);
                   3555:                                                }
                   3556:                                        }
                   3557:                                } else {
                   3558:                                        stack_level--;
                   3559:                                        var = stack[stack_level];
                   3560:                                }
                   3561:                                if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
                   3562:                                        target_hash = HASH_OF(*var);
                   3563:                                        if (target_hash != NULL) {
                   3564:                                                while (zend_hash_get_current_data(target_hash, (void **) &hash_entry) != FAILURE) {
                   3565:                                                        zend_hash_move_forward(target_hash);
                   3566:                                                        if (Z_TYPE_PP(hash_entry) == IS_ARRAY || Z_TYPE_PP(hash_entry) == IS_OBJECT) {
                   3567:                                                                if (stack_level >= stack_max) {
                   3568:                                                                        stack_max += PHP_MBSTR_STACK_BLOCK_SIZE;
                   3569:                                                                        ptmp = erealloc(stack, sizeof(zval **)*stack_max);
                   3570:                                                                        stack = (zval ***)ptmp;
                   3571:                                                                }
                   3572:                                                                stack[stack_level] = var;
                   3573:                                                                stack_level++;
                   3574:                                                                var = hash_entry;
                   3575:                                                                target_hash = HASH_OF(*var);
                   3576:                                                                if (target_hash != NULL) {
                   3577:                                                                        zend_hash_internal_pointer_reset(target_hash);
                   3578:                                                                        continue;
                   3579:                                                                }
                   3580:                                                        } else if (Z_TYPE_PP(hash_entry) == IS_STRING) {
                   3581:                                                                string.val = (unsigned char *)Z_STRVAL_PP(hash_entry);
                   3582:                                                                string.len = Z_STRLEN_PP(hash_entry);
                   3583:                                                                if (mbfl_encoding_detector_feed(identd, &string)) {
                   3584:                                                                        goto detect_end;                /* complete detecting */
                   3585:                                                                }
                   3586:                                                        }
                   3587:                                                }
                   3588:                                        }
                   3589:                                } else if (Z_TYPE_PP(var) == IS_STRING) {
                   3590:                                        string.val = (unsigned char *)Z_STRVAL_PP(var);
                   3591:                                        string.len = Z_STRLEN_PP(var);
                   3592:                                        if (mbfl_encoding_detector_feed(identd, &string)) {
                   3593:                                                goto detect_end;                /* complete detecting */
                   3594:                                        }
                   3595:                                }
                   3596:                        }
                   3597: detect_end:
1.1.1.2   misho    3598:                        from_encoding = mbfl_encoding_detector_judge2(identd);
1.1       misho    3599:                        mbfl_encoding_detector_delete(identd);
                   3600:                }
                   3601:                efree(stack);
                   3602: 
1.1.1.2   misho    3603:                if (!from_encoding) {
1.1       misho    3604:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to detect encoding");
1.1.1.2   misho    3605:                        from_encoding = &mbfl_encoding_pass;
1.1       misho    3606:                }
                   3607:        }
                   3608:        if (elist != NULL) {
                   3609:                efree((void *)elist);
                   3610:        }
                   3611:        /* create converter */
                   3612:        convd = NULL;
1.1.1.2   misho    3613:        if (from_encoding != &mbfl_encoding_pass) {
                   3614:                convd = mbfl_buffer_converter_new2(from_encoding, to_encoding, 0);
1.1       misho    3615:                if (convd == NULL) {
                   3616:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create converter");
                   3617:                        RETURN_FALSE;
                   3618:                }
                   3619:                mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
                   3620:                mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
                   3621:        }
                   3622: 
                   3623:        /* convert */
                   3624:        if (convd != NULL) {
                   3625:                stack_max = PHP_MBSTR_STACK_BLOCK_SIZE;
                   3626:                stack = (zval ***)safe_emalloc(stack_max, sizeof(zval **), 0);
                   3627:                stack_level = 0;
                   3628:                n = 0;
                   3629:                while (n < argc || stack_level > 0) {
                   3630:                        if (stack_level <= 0) {
                   3631:                                var = args[n++];
                   3632:                                if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
                   3633:                                        target_hash = HASH_OF(*var);
                   3634:                                        if (target_hash != NULL) {
                   3635:                                                zend_hash_internal_pointer_reset(target_hash);
                   3636:                                        }
                   3637:                                }
                   3638:                        } else {
                   3639:                                stack_level--;
                   3640:                                var = stack[stack_level];
                   3641:                        }
                   3642:                        if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
                   3643:                                target_hash = HASH_OF(*var);
                   3644:                                if (target_hash != NULL) {
                   3645:                                        while (zend_hash_get_current_data(target_hash, (void **) &hash_entry) != FAILURE) {
                   3646:                                                zend_hash_move_forward(target_hash);
                   3647:                                                if (Z_TYPE_PP(hash_entry) == IS_ARRAY || Z_TYPE_PP(hash_entry) == IS_OBJECT) {
                   3648:                                                        if (stack_level >= stack_max) {
                   3649:                                                                stack_max += PHP_MBSTR_STACK_BLOCK_SIZE;
                   3650:                                                                ptmp = erealloc(stack, sizeof(zval **)*stack_max);
                   3651:                                                                stack = (zval ***)ptmp;
                   3652:                                                        }
                   3653:                                                        stack[stack_level] = var;
                   3654:                                                        stack_level++;
                   3655:                                                        var = hash_entry;
                   3656:                                                        SEPARATE_ZVAL(hash_entry);
                   3657:                                                        target_hash = HASH_OF(*var);
                   3658:                                                        if (target_hash != NULL) {
                   3659:                                                                zend_hash_internal_pointer_reset(target_hash);
                   3660:                                                                continue;
                   3661:                                                        }
                   3662:                                                } else if (Z_TYPE_PP(hash_entry) == IS_STRING) {
                   3663:                                                        string.val = (unsigned char *)Z_STRVAL_PP(hash_entry);
                   3664:                                                        string.len = Z_STRLEN_PP(hash_entry);
                   3665:                                                        ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
                   3666:                                                        if (ret != NULL) {
                   3667:                                                                if (Z_REFCOUNT_PP(hash_entry) > 1) {
                   3668:                                                                        Z_DELREF_PP(hash_entry);
                   3669:                                                                        MAKE_STD_ZVAL(*hash_entry);
                   3670:                                                                } else {
                   3671:                                                                        zval_dtor(*hash_entry);
                   3672:                                                                }
                   3673:                                                        ZVAL_STRINGL(*hash_entry, (char *)ret->val, ret->len, 0);
                   3674:                                                }
                   3675:                                        }
                   3676:                                }
                   3677:                        }
                   3678:                } else if (Z_TYPE_PP(var) == IS_STRING) {
                   3679:                        string.val = (unsigned char *)Z_STRVAL_PP(var);
                   3680:                        string.len = Z_STRLEN_PP(var);
                   3681:                        ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
                   3682:                        if (ret != NULL) {
                   3683:                                zval_dtor(*var);
                   3684:                                ZVAL_STRINGL(*var, (char *)ret->val, ret->len, 0);
                   3685:                                }
                   3686:                        }
                   3687:                }
                   3688:                efree(stack);
                   3689: 
                   3690:                MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
                   3691:                mbfl_buffer_converter_delete(convd);
                   3692:        }
                   3693: 
                   3694:        efree(args);
                   3695: 
1.1.1.2   misho    3696:        if (from_encoding) {
                   3697:                RETURN_STRING(from_encoding->name, 1);
1.1       misho    3698:        } else {
                   3699:                RETURN_FALSE;
                   3700:        }
                   3701: }
                   3702: /* }}} */
                   3703: 
                   3704: /* {{{ HTML numeric entity */
                   3705: /* {{{ static void php_mb_numericentity_exec() */
                   3706: static void
                   3707: php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAMETERS, int type)
                   3708: {
                   3709:        char *str, *encoding;
                   3710:        int str_len, encoding_len;
                   3711:        zval *zconvmap, **hash_entry;
                   3712:        HashTable *target_hash;
                   3713:        size_t argc = ZEND_NUM_ARGS();
                   3714:        int i, *convmap, *mapelm, mapsize=0;
1.1.1.2   misho    3715:        zend_bool is_hex = 0;
1.1       misho    3716:        mbfl_string string, result, *ret;
                   3717:        enum mbfl_no_encoding no_encoding;
                   3718: 
1.1.1.2   misho    3719:        if (zend_parse_parameters(argc TSRMLS_CC, "sz|sb", &str, &str_len, &zconvmap, &encoding, &encoding_len, &is_hex) == FAILURE) {
1.1       misho    3720:                return;
                   3721:        }
                   3722: 
                   3723:        mbfl_string_init(&string);
                   3724:        string.no_language = MBSTRG(language);
1.1.1.2   misho    3725:        string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    3726:        string.val = (unsigned char *)str;
                   3727:        string.len = str_len;
                   3728: 
                   3729:        /* encoding */
1.1.1.2   misho    3730:        if ((argc == 3 || argc == 4) && encoding_len > 0) {
1.1       misho    3731:                no_encoding = mbfl_name2no_encoding(encoding);
                   3732:                if (no_encoding == mbfl_no_encoding_invalid) {
                   3733:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encoding);
                   3734:                        RETURN_FALSE;
                   3735:                } else {
                   3736:                        string.no_encoding = no_encoding;
                   3737:                }
                   3738:        }
                   3739: 
1.1.1.2   misho    3740:        if (argc == 4) {
                   3741:                if (type == 0 && is_hex) {
                   3742:                        type = 2; /* output in hex format */
                   3743:                }
                   3744:        }
                   3745: 
1.1       misho    3746:        /* conversion map */
                   3747:        convmap = NULL;
                   3748:        if (Z_TYPE_P(zconvmap) == IS_ARRAY) {
                   3749:                target_hash = Z_ARRVAL_P(zconvmap);
                   3750:                zend_hash_internal_pointer_reset(target_hash);
                   3751:                i = zend_hash_num_elements(target_hash);
                   3752:                if (i > 0) {
                   3753:                        convmap = (int *)safe_emalloc(i, sizeof(int), 0);
                   3754:                        mapelm = convmap;
                   3755:                        mapsize = 0;
                   3756:                        while (i > 0) {
                   3757:                                if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) {
                   3758:                                        break;
                   3759:                                }
                   3760:                                convert_to_long_ex(hash_entry);
                   3761:                                *mapelm++ = Z_LVAL_PP(hash_entry);
                   3762:                                mapsize++;
                   3763:                                i--;
                   3764:                                zend_hash_move_forward(target_hash);
                   3765:                        }
                   3766:                }
                   3767:        }
                   3768:        if (convmap == NULL) {
                   3769:                RETURN_FALSE;
                   3770:        }
                   3771:        mapsize /= 4;
                   3772: 
                   3773:        ret = mbfl_html_numeric_entity(&string, &result, convmap, mapsize, type);
                   3774:        if (ret != NULL) {
                   3775:                RETVAL_STRINGL((char *)ret->val, ret->len, 0);
                   3776:        } else {
                   3777:                RETVAL_FALSE;
                   3778:        }
                   3779:        efree((void *)convmap);
                   3780: }
                   3781: /* }}} */
                   3782: 
1.1.1.2   misho    3783: /* {{{ proto string mb_encode_numericentity(string string, array convmap [, string encoding [, bool is_hex]])
1.1       misho    3784:    Converts specified characters to HTML numeric entities */
                   3785: PHP_FUNCTION(mb_encode_numericentity)
                   3786: {
                   3787:        php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
                   3788: }
                   3789: /* }}} */
                   3790: 
                   3791: /* {{{ proto string mb_decode_numericentity(string string, array convmap [, string encoding])
                   3792:    Converts HTML numeric entities to character code */
                   3793: PHP_FUNCTION(mb_decode_numericentity)
                   3794: {
                   3795:        php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
                   3796: }
                   3797: /* }}} */
                   3798: /* }}} */
                   3799: 
                   3800: /* {{{ proto int mb_send_mail(string to, string subject, string message [, string additional_headers [, string additional_parameters]])
                   3801:  *  Sends an email message with MIME scheme
                   3802:  */
                   3803: 
                   3804: #define SKIP_LONG_HEADER_SEP_MBSTRING(str, pos)                                                                                \
                   3805:        if (str[pos] == '\r' && str[pos + 1] == '\n' && (str[pos + 2] == ' ' || str[pos + 2] == '\t')) {        \
                   3806:                pos += 2;                                                                                       \
                   3807:                while (str[pos + 1] == ' ' || str[pos + 1] == '\t') {                                                   \
                   3808:                        pos++;                                                                                  \
                   3809:                }                                                                                               \
                   3810:                continue;                                                                                       \
                   3811:        }
                   3812: 
                   3813: #define MAIL_ASCIIZ_CHECK_MBSTRING(str, len)                   \
                   3814:        pp = str;                                       \
                   3815:        ee = pp + len;                                  \
                   3816:        while ((pp = memchr(pp, '\0', (ee - pp)))) {    \
                   3817:                *pp = ' ';                              \
                   3818:        }                                               \
                   3819: 
                   3820: #define APPEND_ONE_CHAR(ch) do { \
                   3821:        if (token.a > 0) { \
                   3822:                smart_str_appendc(&token, ch); \
                   3823:        } else {\
                   3824:                token.len++; \
                   3825:        } \
                   3826: } while (0)
                   3827: 
                   3828: #define SEPARATE_SMART_STR(str) do {\
                   3829:        if ((str)->a == 0) { \
                   3830:                char *tmp_ptr; \
                   3831:                (str)->a = 1; \
                   3832:                while ((str)->a < (str)->len) { \
                   3833:                        (str)->a <<= 1; \
                   3834:                } \
                   3835:                tmp_ptr = emalloc((str)->a + 1); \
                   3836:                memcpy(tmp_ptr, (str)->c, (str)->len); \
                   3837:                (str)->c = tmp_ptr; \
                   3838:        } \
                   3839: } while (0)
                   3840: 
                   3841: static void my_smart_str_dtor(smart_str *s)
                   3842: {
                   3843:        if (s->a > 0) {
                   3844:                smart_str_free(s);
                   3845:        }
                   3846: }
                   3847: 
                   3848: static int _php_mbstr_parse_mail_headers(HashTable *ht, const char *str, size_t str_len)
                   3849: {
                   3850:        const char *ps;
                   3851:        size_t icnt;
                   3852:        int state = 0;
                   3853:        int crlf_state = -1;
                   3854: 
                   3855:        smart_str token = { 0, 0, 0 };
                   3856:        smart_str fld_name = { 0, 0, 0 }, fld_val = { 0, 0, 0 };
                   3857: 
                   3858:        ps = str;
                   3859:        icnt = str_len;
                   3860: 
                   3861:        /*
                   3862:         *             C o n t e n t - T y p e :   t e x t / h t m l \r\n
                   3863:         *             ^ ^^^^^^^^^^^^^^^^^^^^^ ^^^ ^^^^^^^^^^^^^^^^^ ^^^^ 
                   3864:         *      state  0            1           2          3          
                   3865:         *
                   3866:         *             C o n t e n t - T y p e :   t e x t / h t m l \r\n
                   3867:         *             ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ 
                   3868:         * crlf_state -1                       0                     1 -1  
                   3869:         *
                   3870:         */
                   3871: 
                   3872:        while (icnt > 0) {
                   3873:                switch (*ps) {
                   3874:                        case ':':
                   3875:                                if (crlf_state == 1) {
                   3876:                                        APPEND_ONE_CHAR('\r');
                   3877:                                }
                   3878: 
                   3879:                                if (state == 0 || state == 1) {
                   3880:                                        fld_name = token;
                   3881: 
                   3882:                                        state = 2;
                   3883:                                } else {
                   3884:                                        APPEND_ONE_CHAR(*ps);
                   3885:                                }
                   3886: 
                   3887:                                crlf_state = 0;
                   3888:                                break;
                   3889: 
                   3890:                        case '\n':
                   3891:                                if (crlf_state == -1) {
                   3892:                                        goto out;
                   3893:                                }
                   3894:                                crlf_state = -1;
                   3895:                                break;
                   3896: 
                   3897:                        case '\r':
                   3898:                                if (crlf_state == 1) {
                   3899:                                        APPEND_ONE_CHAR('\r');
                   3900:                                } else {
                   3901:                                        crlf_state = 1;
                   3902:                                }
                   3903:                                break;
                   3904: 
                   3905:                        case ' ': case '\t':
                   3906:                                if (crlf_state == -1) {
                   3907:                                        if (state == 3) {
                   3908:                                                /* continuing from the previous line */
                   3909:                                                SEPARATE_SMART_STR(&token);
                   3910:                                                state = 4;
                   3911:                                        } else {
                   3912:                                                /* simply skipping this new line */
                   3913:                                                state = 5;
                   3914:                                        }
                   3915:                                } else {
                   3916:                                        if (crlf_state == 1) {
                   3917:                                                APPEND_ONE_CHAR('\r');
                   3918:                                        }
                   3919:                                        if (state == 1 || state == 3) {
                   3920:                                                APPEND_ONE_CHAR(*ps);
                   3921:                                        }
                   3922:                                }
                   3923:                                crlf_state = 0;
                   3924:                                break;
                   3925: 
                   3926:                        default:
                   3927:                                switch (state) {
                   3928:                                        case 0:
                   3929:                                                token.c = (char *)ps;
                   3930:                                                token.len = 0;
                   3931:                                                token.a = 0;
                   3932:                                                state = 1;
                   3933:                                                break;
                   3934:                                        
                   3935:                                        case 2:
                   3936:                                                if (crlf_state != -1) {
                   3937:                                                        token.c = (char *)ps;
                   3938:                                                        token.len = 0;
                   3939:                                                        token.a = 0;
                   3940: 
                   3941:                                                        state = 3;
                   3942:                                                        break;
                   3943:                                                }
                   3944:                                                /* break is missing intentionally */
                   3945: 
                   3946:                                        case 3:
                   3947:                                                if (crlf_state == -1) {
                   3948:                                                        fld_val = token;
                   3949: 
                   3950:                                                        if (fld_name.c != NULL && fld_val.c != NULL) {
                   3951:                                                                char *dummy;
                   3952: 
                   3953:                                                                /* FIXME: some locale free implementation is
                   3954:                                                                 * really required here,,, */
                   3955:                                                                SEPARATE_SMART_STR(&fld_name);
                   3956:                                                                php_strtoupper(fld_name.c, fld_name.len);
                   3957: 
                   3958:                                                                zend_hash_update(ht, (char *)fld_name.c, fld_name.len, &fld_val, sizeof(smart_str), (void **)&dummy);
                   3959: 
                   3960:                                                                my_smart_str_dtor(&fld_name);
                   3961:                                                        }
                   3962: 
                   3963:                                                        memset(&fld_name, 0, sizeof(smart_str));
                   3964:                                                        memset(&fld_val, 0, sizeof(smart_str));
                   3965: 
                   3966:                                                        token.c = (char *)ps;
                   3967:                                                        token.len = 0;
                   3968:                                                        token.a = 0;
                   3969: 
                   3970:                                                        state = 1;
                   3971:                                                }
                   3972:                                                break;
                   3973: 
                   3974:                                        case 4:
                   3975:                                                APPEND_ONE_CHAR(' ');
                   3976:                                                state = 3;
                   3977:                                                break;
                   3978:                                }
                   3979: 
                   3980:                                if (crlf_state == 1) {
                   3981:                                        APPEND_ONE_CHAR('\r');
                   3982:                                }
                   3983: 
                   3984:                                APPEND_ONE_CHAR(*ps);
                   3985: 
                   3986:                                crlf_state = 0;
                   3987:                                break;
                   3988:                }
                   3989:                ps++, icnt--;
                   3990:        }
                   3991: out:
                   3992:        if (state == 2) {
                   3993:                token.c = "";
                   3994:                token.len = 0;
                   3995:                token.a = 0;
                   3996: 
                   3997:                state = 3;
                   3998:        }
                   3999:        if (state == 3) {
                   4000:                fld_val = token;
                   4001: 
                   4002:                if (fld_name.c != NULL && fld_val.c != NULL) {
                   4003:                        void *dummy;
                   4004: 
                   4005:                        /* FIXME: some locale free implementation is
                   4006:                         * really required here,,, */
                   4007:                        SEPARATE_SMART_STR(&fld_name);
                   4008:                        php_strtoupper(fld_name.c, fld_name.len);
                   4009: 
                   4010:                        zend_hash_update(ht, (char *)fld_name.c, fld_name.len, &fld_val, sizeof(smart_str), (void **)&dummy);
                   4011: 
                   4012:                        my_smart_str_dtor(&fld_name);
                   4013:                }
                   4014:        }
                   4015:        return state;
                   4016: }
                   4017: 
                   4018: PHP_FUNCTION(mb_send_mail)
                   4019: {
                   4020:        int n;
                   4021:        char *to = NULL;
                   4022:        int to_len;
                   4023:        char *message = NULL;
                   4024:        int message_len;
                   4025:        char *headers = NULL;
                   4026:        int headers_len;
                   4027:        char *subject = NULL;
                   4028:        int subject_len;
                   4029:        char *extra_cmd = NULL;
                   4030:        int extra_cmd_len;
                   4031:        int i;
                   4032:        char *to_r = NULL;
                   4033:        char *force_extra_parameters = INI_STR("mail.force_extra_parameters");
                   4034:        struct {
                   4035:                int cnt_type:1;
                   4036:                int cnt_trans_enc:1;
                   4037:        } suppressed_hdrs = { 0, 0 };
                   4038: 
                   4039:        char *message_buf = NULL, *subject_buf = NULL, *p;
                   4040:        mbfl_string orig_str, conv_str;
                   4041:        mbfl_string *pstr;      /* pointer to mbfl string for return value */
                   4042:        enum mbfl_no_encoding
1.1.1.2   misho    4043:                tran_cs,        /* transfar text charset */
                   4044:                head_enc,       /* header transfar encoding */
                   4045:                body_enc;       /* body transfar encoding */
1.1       misho    4046:        mbfl_memory_device device;      /* automatic allocateable buffer for additional header */
                   4047:        const mbfl_language *lang;
                   4048:        int err = 0;
                   4049:        HashTable ht_headers;
                   4050:        smart_str *s;
                   4051:        extern void mbfl_memory_device_unput(mbfl_memory_device *device);
                   4052:        char *pp, *ee;
1.1.1.2   misho    4053: 
1.1       misho    4054:        /* initialize */
                   4055:        mbfl_memory_device_init(&device, 0, 0);
                   4056:        mbfl_string_init(&orig_str);
                   4057:        mbfl_string_init(&conv_str);
                   4058: 
                   4059:        /* character-set, transfer-encoding */
                   4060:        tran_cs = mbfl_no_encoding_utf8;
                   4061:        head_enc = mbfl_no_encoding_base64;
                   4062:        body_enc = mbfl_no_encoding_base64;
                   4063:        lang = mbfl_no2language(MBSTRG(language));
                   4064:        if (lang != NULL) {
                   4065:                tran_cs = lang->mail_charset;
                   4066:                head_enc = lang->mail_header_encoding;
                   4067:                body_enc = lang->mail_body_encoding;
                   4068:        }
                   4069: 
                   4070:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ss", &to, &to_len, &subject, &subject_len, &message, &message_len, &headers, &headers_len, &extra_cmd, &extra_cmd_len) == FAILURE) {
                   4071:                return;
                   4072:        }
                   4073: 
                   4074:        /* ASCIIZ check */
                   4075:        MAIL_ASCIIZ_CHECK_MBSTRING(to, to_len);
                   4076:        MAIL_ASCIIZ_CHECK_MBSTRING(subject, subject_len);
                   4077:        MAIL_ASCIIZ_CHECK_MBSTRING(message, message_len);
                   4078:        if (headers) {
                   4079:                MAIL_ASCIIZ_CHECK_MBSTRING(headers, headers_len);
                   4080:        }
                   4081:        if (extra_cmd) {
                   4082:                MAIL_ASCIIZ_CHECK_MBSTRING(extra_cmd, extra_cmd_len);
                   4083:        }
                   4084: 
                   4085:        zend_hash_init(&ht_headers, 0, NULL, (dtor_func_t) my_smart_str_dtor, 0);
                   4086: 
                   4087:        if (headers != NULL) {
                   4088:                _php_mbstr_parse_mail_headers(&ht_headers, headers, headers_len);
                   4089:        }
                   4090: 
                   4091:        if (zend_hash_find(&ht_headers, "CONTENT-TYPE", sizeof("CONTENT-TYPE") - 1, (void **)&s) == SUCCESS) {
                   4092:                char *tmp;
                   4093:                char *param_name;
                   4094:                char *charset = NULL;
                   4095: 
                   4096:                SEPARATE_SMART_STR(s);
                   4097:                smart_str_0(s);
                   4098: 
                   4099:                p = strchr(s->c, ';');
                   4100: 
                   4101:                if (p != NULL) {
                   4102:                        /* skipping the padded spaces */
                   4103:                        do {
                   4104:                                ++p;
                   4105:                        } while (*p == ' ' || *p == '\t');
                   4106: 
                   4107:                        if (*p != '\0') {
                   4108:                                if ((param_name = php_strtok_r(p, "= ", &tmp)) != NULL) {
                   4109:                                        if (strcasecmp(param_name, "charset") == 0) {
                   4110:                                                enum mbfl_no_encoding _tran_cs = tran_cs;
                   4111:                                                
                   4112:                                                charset = php_strtok_r(NULL, "= \"", &tmp);
                   4113:                                                if (charset != NULL) {
                   4114:                                                        _tran_cs = mbfl_name2no_encoding(charset);
                   4115:                                                }
                   4116: 
                   4117:                                                if (_tran_cs == mbfl_no_encoding_invalid) {
                   4118:                                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported charset \"%s\" - will be regarded as ascii", charset); 
                   4119:                                                        _tran_cs = mbfl_no_encoding_ascii;
                   4120:                                                }
                   4121:                                                tran_cs = _tran_cs;
                   4122:                                        }
                   4123:                                }
                   4124:                        }
                   4125:                }
                   4126:                suppressed_hdrs.cnt_type = 1;
                   4127:        }
                   4128: 
                   4129:        if (zend_hash_find(&ht_headers, "CONTENT-TRANSFER-ENCODING", sizeof("CONTENT-TRANSFER-ENCODING") - 1, (void **)&s) == SUCCESS) {
                   4130:                enum mbfl_no_encoding _body_enc;
                   4131:                SEPARATE_SMART_STR(s);
                   4132:                smart_str_0(s);
                   4133: 
                   4134:                _body_enc = mbfl_name2no_encoding(s->c);
                   4135:                switch (_body_enc) {
                   4136:                        case mbfl_no_encoding_base64:
                   4137:                        case mbfl_no_encoding_7bit:
                   4138:                        case mbfl_no_encoding_8bit:
                   4139:                                body_enc = _body_enc;
                   4140:                                break;
                   4141: 
                   4142:                        default:
                   4143:                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported transfer encoding \"%s\" - will be regarded as 8bit", s->c); 
                   4144:                                body_enc =      mbfl_no_encoding_8bit;
                   4145:                                break;
                   4146:                }
                   4147:                suppressed_hdrs.cnt_trans_enc = 1;
                   4148:        }
                   4149: 
                   4150:        /* To: */
                   4151:        if (to != NULL) {
1.1.1.2   misho    4152:                if (to_len > 0) {
                   4153:                        to_r = estrndup(to, to_len);
                   4154:                        for (; to_len; to_len--) {
                   4155:                                if (!isspace((unsigned char) to_r[to_len - 1])) {
                   4156:                                        break;
                   4157:                                }
                   4158:                                to_r[to_len - 1] = '\0';
                   4159:                        }
                   4160:                        for (i = 0; to_r[i]; i++) {
1.1       misho    4161:                        if (iscntrl((unsigned char) to_r[i])) {
                   4162:                                /* According to RFC 822, section 3.1.1 long headers may be separated into
                   4163:                                 * parts using CRLF followed at least one linear-white-space character ('\t' or ' ').
                   4164:                                 * To prevent these separators from being replaced with a space, we use the
                   4165:                                 * SKIP_LONG_HEADER_SEP_MBSTRING to skip over them.
                   4166:                                 */
                   4167:                                SKIP_LONG_HEADER_SEP_MBSTRING(to_r, i);
                   4168:                                to_r[i] = ' ';
                   4169:                        }
1.1.1.2   misho    4170:                        }
                   4171:                } else {
                   4172:                        to_r = to;
                   4173:                }
                   4174:        } else {
1.1       misho    4175:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing To: field");
                   4176:                err = 1;
                   4177:        }
                   4178: 
                   4179:        /* Subject: */
                   4180:        if (subject != NULL && subject_len >= 0) {
                   4181:                orig_str.no_language = MBSTRG(language);
                   4182:                orig_str.val = (unsigned char *)subject;
                   4183:                orig_str.len = subject_len;
1.1.1.2   misho    4184:                orig_str.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
                   4185:                if (orig_str.no_encoding == mbfl_no_encoding_invalid || orig_str.no_encoding == mbfl_no_encoding_pass) {
                   4186:                        const mbfl_encoding *encoding = mbfl_identify_encoding2(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection));
                   4187:                        orig_str.no_encoding = encoding ? encoding->no_encoding: mbfl_no_encoding_invalid;
1.1       misho    4188:                }
                   4189:                pstr = mbfl_mime_header_encode(&orig_str, &conv_str, tran_cs, head_enc, "\n", sizeof("Subject: [PHP-jp nnnnnnnn]"));
                   4190:                if (pstr != NULL) {
                   4191:                        subject_buf = subject = (char *)pstr->val;
                   4192:                }
                   4193:        } else {
                   4194:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing Subject: field");
                   4195:                err = 1;
                   4196:        }
                   4197: 
                   4198:        /* message body */
                   4199:        if (message != NULL) {
                   4200:                orig_str.no_language = MBSTRG(language);
                   4201:                orig_str.val = (unsigned char *)message;
                   4202:                orig_str.len = (unsigned int)message_len;
1.1.1.2   misho    4203:                orig_str.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    4204: 
1.1.1.2   misho    4205:                if (orig_str.no_encoding == mbfl_no_encoding_invalid || orig_str.no_encoding == mbfl_no_encoding_pass) {
                   4206:                        const mbfl_encoding *encoding = mbfl_identify_encoding2(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection));
                   4207:                        orig_str.no_encoding = encoding ? encoding->no_encoding: mbfl_no_encoding_invalid;
1.1       misho    4208:                }
                   4209: 
                   4210:                pstr = NULL;
                   4211:                {
                   4212:                        mbfl_string tmpstr;
                   4213: 
                   4214:                        if (mbfl_convert_encoding(&orig_str, &tmpstr, tran_cs) != NULL) {
                   4215:                                tmpstr.no_encoding=mbfl_no_encoding_8bit;
                   4216:                                pstr = mbfl_convert_encoding(&tmpstr, &conv_str, body_enc);
                   4217:                                efree(tmpstr.val);
                   4218:                        }
                   4219:                }
                   4220:                if (pstr != NULL) {
                   4221:                        message_buf = message = (char *)pstr->val;
                   4222:                }
                   4223:        } else {
                   4224:                /* this is not really an error, so it is allowed. */
                   4225:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty message body");
                   4226:                message = NULL;
                   4227:        }
                   4228: 
                   4229:        /* other headers */
                   4230: #define PHP_MBSTR_MAIL_MIME_HEADER1 "MIME-Version: 1.0"
                   4231: #define PHP_MBSTR_MAIL_MIME_HEADER2 "Content-Type: text/plain"
                   4232: #define PHP_MBSTR_MAIL_MIME_HEADER3 "; charset="
                   4233: #define PHP_MBSTR_MAIL_MIME_HEADER4 "Content-Transfer-Encoding: "
                   4234:        if (headers != NULL) {
                   4235:                p = headers;
                   4236:                n = headers_len;
                   4237:                mbfl_memory_device_strncat(&device, p, n);
                   4238:                if (n > 0 && p[n - 1] != '\n') {
                   4239:                        mbfl_memory_device_strncat(&device, "\n", 1);
                   4240:                }
                   4241:        }
                   4242: 
                   4243:        if (!zend_hash_exists(&ht_headers, "MIME-VERSION", sizeof("MIME-VERSION") - 1)) {
                   4244:                mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER1, sizeof(PHP_MBSTR_MAIL_MIME_HEADER1) - 1);
                   4245:                mbfl_memory_device_strncat(&device, "\n", 1);
                   4246:        }
                   4247: 
                   4248:        if (!suppressed_hdrs.cnt_type) {
                   4249:                mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER2, sizeof(PHP_MBSTR_MAIL_MIME_HEADER2) - 1);
                   4250: 
                   4251:                p = (char *)mbfl_no2preferred_mime_name(tran_cs);
                   4252:                if (p != NULL) {
                   4253:                        mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER3, sizeof(PHP_MBSTR_MAIL_MIME_HEADER3) - 1);
                   4254:                        mbfl_memory_device_strcat(&device, p);
                   4255:                }
                   4256:                mbfl_memory_device_strncat(&device, "\n", 1);
                   4257:        }
                   4258:        if (!suppressed_hdrs.cnt_trans_enc) {
                   4259:                mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER4, sizeof(PHP_MBSTR_MAIL_MIME_HEADER4) - 1);
                   4260:                p = (char *)mbfl_no2preferred_mime_name(body_enc);
                   4261:                if (p == NULL) {
                   4262:                        p = "7bit";
                   4263:                }
                   4264:                mbfl_memory_device_strcat(&device, p);
                   4265:                mbfl_memory_device_strncat(&device, "\n", 1);
                   4266:        }
                   4267: 
                   4268:        mbfl_memory_device_unput(&device);
                   4269:        mbfl_memory_device_output('\0', &device);
                   4270:        headers = (char *)device.buffer;
                   4271: 
                   4272:        if (force_extra_parameters) {
                   4273:                extra_cmd = php_escape_shell_cmd(force_extra_parameters);
                   4274:        } else if (extra_cmd) {
                   4275:                extra_cmd = php_escape_shell_cmd(extra_cmd);
                   4276:        } 
                   4277: 
                   4278:        if (!err && php_mail(to_r, subject, message, headers, extra_cmd TSRMLS_CC)) {
                   4279:                RETVAL_TRUE;
                   4280:        } else {
                   4281:                RETVAL_FALSE;
                   4282:        }
                   4283: 
                   4284:        if (extra_cmd) {
                   4285:                efree(extra_cmd);
                   4286:        }
                   4287:        if (to_r != to) {
                   4288:                efree(to_r);
                   4289:        }
                   4290:        if (subject_buf) {
                   4291:                efree((void *)subject_buf);
                   4292:        }
                   4293:        if (message_buf) {
                   4294:                efree((void *)message_buf);
                   4295:        }
                   4296:        mbfl_memory_device_clear(&device);
                   4297:        zend_hash_destroy(&ht_headers);
                   4298: }
                   4299: 
                   4300: #undef SKIP_LONG_HEADER_SEP_MBSTRING
                   4301: #undef MAIL_ASCIIZ_CHECK_MBSTRING
                   4302: #undef APPEND_ONE_CHAR
                   4303: #undef SEPARATE_SMART_STR
                   4304: #undef PHP_MBSTR_MAIL_MIME_HEADER1
                   4305: #undef PHP_MBSTR_MAIL_MIME_HEADER2
                   4306: #undef PHP_MBSTR_MAIL_MIME_HEADER3
                   4307: #undef PHP_MBSTR_MAIL_MIME_HEADER4
                   4308: /* }}} */
                   4309: 
                   4310: /* {{{ proto mixed mb_get_info([string type])
                   4311:    Returns the current settings of mbstring */
                   4312: PHP_FUNCTION(mb_get_info)
                   4313: {
                   4314:        char *typ = NULL;
1.1.1.2   misho    4315:        int typ_len;
                   4316:        size_t n;
1.1       misho    4317:        char *name;
                   4318:        const struct mb_overload_def *over_func;
                   4319:        zval *row1, *row2;
                   4320:        const mbfl_language *lang = mbfl_no2language(MBSTRG(language));
1.1.1.2   misho    4321:        const mbfl_encoding **entry;
1.1       misho    4322: 
                   4323:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &typ, &typ_len) == FAILURE) {
                   4324:                RETURN_FALSE;
                   4325:        }
                   4326: 
                   4327:        if (!typ || !strcasecmp("all", typ)) {
                   4328:                array_init(return_value);
1.1.1.2   misho    4329:                if (MBSTRG(current_internal_encoding)) {
                   4330:                        add_assoc_string(return_value, "internal_encoding", (char *)MBSTRG(current_internal_encoding)->name, 1);
1.1       misho    4331:                }
1.1.1.2   misho    4332:                if (MBSTRG(http_input_identify)) {
                   4333:                        add_assoc_string(return_value, "http_input", (char *)MBSTRG(http_input_identify)->name, 1);
1.1       misho    4334:                }
1.1.1.2   misho    4335:                if (MBSTRG(current_http_output_encoding)) {
                   4336:                        add_assoc_string(return_value, "http_output", (char *)MBSTRG(current_http_output_encoding)->name, 1);
1.1       misho    4337:                }
                   4338:                if ((name = (char *)zend_ini_string("mbstring.http_output_conv_mimetypes", sizeof("mbstring.http_output_conv_mimetypes"), 0)) != NULL) {
                   4339:                        add_assoc_string(return_value, "http_output_conv_mimetypes", name, 1);
                   4340:                }
                   4341:                add_assoc_long(return_value, "func_overload", MBSTRG(func_overload));
                   4342:                if (MBSTRG(func_overload)){
                   4343:                        over_func = &(mb_ovld[0]);
                   4344:                        MAKE_STD_ZVAL(row1);
                   4345:                        array_init(row1);
                   4346:                        while (over_func->type > 0) {
                   4347:                                if ((MBSTRG(func_overload) & over_func->type) == over_func->type ) {
                   4348:                                        add_assoc_string(row1, over_func->orig_func, over_func->ovld_func, 1);
                   4349:                                }
                   4350:                                over_func++;
                   4351:                        }
                   4352:                        add_assoc_zval(return_value, "func_overload_list", row1);
                   4353:                } else {
                   4354:                        add_assoc_string(return_value, "func_overload_list", "no overload", 1);
                   4355:                }
                   4356:                if (lang != NULL) {
                   4357:                        if ((name = (char *)mbfl_no_encoding2name(lang->mail_charset)) != NULL) {
                   4358:                                add_assoc_string(return_value, "mail_charset", name, 1);
                   4359:                        }
                   4360:                        if ((name = (char *)mbfl_no_encoding2name(lang->mail_header_encoding)) != NULL) {
                   4361:                                add_assoc_string(return_value, "mail_header_encoding", name, 1);
                   4362:                        }
                   4363:                        if ((name = (char *)mbfl_no_encoding2name(lang->mail_body_encoding)) != NULL) {
                   4364:                                add_assoc_string(return_value, "mail_body_encoding", name, 1);
                   4365:                        }
                   4366:                }
                   4367:                add_assoc_long(return_value, "illegal_chars", MBSTRG(illegalchars));
                   4368:                if (MBSTRG(encoding_translation)) {
                   4369:                        add_assoc_string(return_value, "encoding_translation", "On", 1);
                   4370:                } else {
                   4371:                        add_assoc_string(return_value, "encoding_translation", "Off", 1);
                   4372:                }
                   4373:                if ((name = (char *)mbfl_no_language2name(MBSTRG(language))) != NULL) {
                   4374:                        add_assoc_string(return_value, "language", name, 1);
                   4375:                }               
                   4376:                n = MBSTRG(current_detect_order_list_size);
                   4377:                entry = MBSTRG(current_detect_order_list);
1.1.1.2   misho    4378:                if (n > 0) {
                   4379:                        size_t i;
1.1       misho    4380:                        MAKE_STD_ZVAL(row2);
                   4381:                        array_init(row2);
1.1.1.2   misho    4382:                        for (i = 0; i < n; i++) {
                   4383:                                add_next_index_string(row2, (*entry)->name, 1);
1.1       misho    4384:                                entry++;
                   4385:                        }
                   4386:                        add_assoc_zval(return_value, "detect_order", row2);
                   4387:                }
                   4388:                if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
                   4389:                        add_assoc_string(return_value, "substitute_character", "none", 1);
                   4390:                } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG) {
                   4391:                        add_assoc_string(return_value, "substitute_character", "long", 1);
                   4392:                } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY) {
                   4393:                        add_assoc_string(return_value, "substitute_character", "entity", 1);
                   4394:                } else {
                   4395:                        add_assoc_long(return_value, "substitute_character", MBSTRG(current_filter_illegal_substchar));
                   4396:                }
                   4397:                if (MBSTRG(strict_detection)) {
                   4398:                        add_assoc_string(return_value, "strict_detection", "On", 1);
                   4399:                } else {
                   4400:                        add_assoc_string(return_value, "strict_detection", "Off", 1);
                   4401:                }
                   4402:        } else if (!strcasecmp("internal_encoding", typ)) {
1.1.1.2   misho    4403:                if (MBSTRG(current_internal_encoding)) {
                   4404:                        RETVAL_STRING((char *)MBSTRG(current_internal_encoding)->name, 1);
1.1       misho    4405:                }               
                   4406:        } else if (!strcasecmp("http_input", typ)) {
1.1.1.2   misho    4407:                if (MBSTRG(http_input_identify)) {
                   4408:                        RETVAL_STRING((char *)MBSTRG(http_input_identify)->name, 1);
1.1       misho    4409:                }               
                   4410:        } else if (!strcasecmp("http_output", typ)) {
1.1.1.2   misho    4411:                if (MBSTRG(current_http_output_encoding)) {
                   4412:                        RETVAL_STRING((char *)MBSTRG(current_http_output_encoding)->name, 1);
1.1       misho    4413:                }               
                   4414:        } else if (!strcasecmp("http_output_conv_mimetypes", typ)) {
                   4415:                if ((name = (char *)zend_ini_string("mbstring.http_output_conv_mimetypes", sizeof("mbstring.http_output_conv_mimetypes"), 0)) != NULL) {
                   4416:                        RETVAL_STRING(name, 1);
                   4417:                }
                   4418:        } else if (!strcasecmp("func_overload", typ)) {
                   4419:                RETVAL_LONG(MBSTRG(func_overload));
                   4420:        } else if (!strcasecmp("func_overload_list", typ)) {
                   4421:                if (MBSTRG(func_overload)){
                   4422:                                over_func = &(mb_ovld[0]);
                   4423:                                array_init(return_value);
                   4424:                                while (over_func->type > 0) {
                   4425:                                        if ((MBSTRG(func_overload) & over_func->type) == over_func->type ) {
                   4426:                                                add_assoc_string(return_value, over_func->orig_func, over_func->ovld_func, 1);
                   4427:                                        }
                   4428:                                        over_func++;
                   4429:                                }
                   4430:                } else {
                   4431:                        RETVAL_STRING("no overload", 1);
                   4432:                }
                   4433:        } else if (!strcasecmp("mail_charset", typ)) {
                   4434:                if (lang != NULL && (name = (char *)mbfl_no_encoding2name(lang->mail_charset)) != NULL) {
                   4435:                        RETVAL_STRING(name, 1);
                   4436:                }
                   4437:        } else if (!strcasecmp("mail_header_encoding", typ)) {
                   4438:                if (lang != NULL && (name = (char *)mbfl_no_encoding2name(lang->mail_header_encoding)) != NULL) {
                   4439:                        RETVAL_STRING(name, 1);
                   4440:                }
                   4441:        } else if (!strcasecmp("mail_body_encoding", typ)) {
                   4442:                if (lang != NULL && (name = (char *)mbfl_no_encoding2name(lang->mail_body_encoding)) != NULL) {
                   4443:                        RETVAL_STRING(name, 1);
                   4444:                }
                   4445:        } else if (!strcasecmp("illegal_chars", typ)) {
                   4446:                RETVAL_LONG(MBSTRG(illegalchars));
                   4447:        } else if (!strcasecmp("encoding_translation", typ)) {
                   4448:                if (MBSTRG(encoding_translation)) {
                   4449:                        RETVAL_STRING("On", 1);
                   4450:                } else {
                   4451:                        RETVAL_STRING("Off", 1);
                   4452:                }
                   4453:        } else if (!strcasecmp("language", typ)) {
                   4454:                if ((name = (char *)mbfl_no_language2name(MBSTRG(language))) != NULL) {
                   4455:                        RETVAL_STRING(name, 1);
                   4456:                }               
                   4457:        } else if (!strcasecmp("detect_order", typ)) {
                   4458:                n = MBSTRG(current_detect_order_list_size);
                   4459:                entry = MBSTRG(current_detect_order_list);
1.1.1.2   misho    4460:                if (n > 0) {
                   4461:                        size_t i;
1.1       misho    4462:                        array_init(return_value);
1.1.1.2   misho    4463:                        for (i = 0; i < n; i++) {
                   4464:                                add_next_index_string(return_value, (*entry)->name, 1);
1.1       misho    4465:                                entry++;
                   4466:                        }
                   4467:                }
                   4468:        } else if (!strcasecmp("substitute_character", typ)) {
                   4469:                if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
                   4470:                        RETVAL_STRING("none", 1);
                   4471:                } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG) {
                   4472:                        RETVAL_STRING("long", 1);
                   4473:                } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY) {
                   4474:                        RETVAL_STRING("entity", 1);
                   4475:                } else {
                   4476:                        RETVAL_LONG(MBSTRG(current_filter_illegal_substchar));
                   4477:                }
                   4478:        } else if (!strcasecmp("strict_detection", typ)) {
                   4479:                if (MBSTRG(strict_detection)) {
                   4480:                        RETVAL_STRING("On", 1);
                   4481:                } else {
                   4482:                        RETVAL_STRING("Off", 1);
                   4483:                }
                   4484:        } else {
                   4485:                RETURN_FALSE;
                   4486:        }
                   4487: }
                   4488: /* }}} */
                   4489: 
                   4490: /* {{{ proto bool mb_check_encoding([string var[, string encoding]])
                   4491:    Check if the string is valid for the specified encoding */
                   4492: PHP_FUNCTION(mb_check_encoding)
                   4493: {
                   4494:        char *var = NULL;
                   4495:        int var_len;
                   4496:        char *enc = NULL;
                   4497:        int enc_len;
                   4498:        mbfl_buffer_converter *convd;
1.1.1.2   misho    4499:        const mbfl_encoding *encoding = MBSTRG(current_internal_encoding);
1.1       misho    4500:        mbfl_string string, result, *ret = NULL;
                   4501:        long illegalchars = 0;
                   4502: 
                   4503:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &var, &var_len, &enc, &enc_len) == FAILURE) {
                   4504:                RETURN_FALSE;
                   4505:        }
                   4506: 
                   4507:        if (var == NULL) {
                   4508:                RETURN_BOOL(MBSTRG(illegalchars) == 0);
                   4509:        }
                   4510: 
                   4511:        if (enc != NULL) {
1.1.1.2   misho    4512:                encoding = mbfl_name2encoding(enc);
                   4513:                if (!encoding || encoding == &mbfl_encoding_pass) {
1.1       misho    4514:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid encoding \"%s\"", enc);
                   4515:                        RETURN_FALSE;
                   4516:                }
                   4517:        }
1.1.1.2   misho    4518: 
                   4519:        convd = mbfl_buffer_converter_new2(encoding, encoding, 0);
1.1       misho    4520:        if (convd == NULL) {
                   4521:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create converter");
                   4522:                RETURN_FALSE;
                   4523:        }       
                   4524:        mbfl_buffer_converter_illegal_mode(convd, MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE);
                   4525:        mbfl_buffer_converter_illegal_substchar(convd, 0);      
1.1.1.2   misho    4526: 
1.1       misho    4527:        /* initialize string */
1.1.1.2   misho    4528:        mbfl_string_init_set(&string, mbfl_no_language_neutral, encoding->no_encoding);
1.1       misho    4529:        mbfl_string_init(&result);
                   4530: 
                   4531:        string.val = (unsigned char *)var;
                   4532:        string.len = var_len;
                   4533:        ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
                   4534:        illegalchars = mbfl_buffer_illegalchars(convd);
                   4535:        mbfl_buffer_converter_delete(convd);
                   4536: 
                   4537:        RETVAL_FALSE;
                   4538:        if (ret != NULL) {
                   4539:                if (illegalchars == 0 && string.len == result.len && memcmp(string.val, result.val, string.len) == 0) {
                   4540:                        RETVAL_TRUE;
                   4541:                }
                   4542:                mbfl_string_clear(&result);
                   4543:        }
                   4544: }
                   4545: /* }}} */
                   4546: 
1.1.1.2   misho    4547: 
                   4548: /* {{{ php_mb_populate_current_detect_order_list */
                   4549: static void php_mb_populate_current_detect_order_list(TSRMLS_D)
                   4550: {
                   4551:        const mbfl_encoding **entry = 0;
                   4552:        size_t nentries;
                   4553: 
                   4554:        if (MBSTRG(current_detect_order_list)) {
                   4555:                return;
                   4556:        }
                   4557: 
                   4558:        if (MBSTRG(detect_order_list) && MBSTRG(detect_order_list_size)) {
                   4559:                nentries = MBSTRG(detect_order_list_size);
                   4560:                entry = (const mbfl_encoding **)safe_emalloc(nentries, sizeof(mbfl_encoding*), 0);
                   4561:                memcpy(entry, MBSTRG(detect_order_list), sizeof(mbfl_encoding*) * nentries);
                   4562:        } else {
                   4563:                const enum mbfl_no_encoding *src = MBSTRG(default_detect_order_list);
                   4564:                size_t i;
                   4565:                nentries = MBSTRG(default_detect_order_list_size);
                   4566:                entry = (const mbfl_encoding **)safe_emalloc(nentries, sizeof(mbfl_encoding*), 0);
                   4567:                for (i = 0; i < nentries; i++) {
                   4568:                        entry[i] = mbfl_no2encoding(src[i]);
                   4569:                }
                   4570:        }
                   4571:        MBSTRG(current_detect_order_list) = entry;
                   4572:        MBSTRG(current_detect_order_list_size) = nentries;
                   4573: }
                   4574: 
                   4575: /* {{{ static int php_mb_encoding_translation() */
                   4576: static int php_mb_encoding_translation(TSRMLS_D) 
1.1       misho    4577: {
                   4578:        return MBSTRG(encoding_translation);
                   4579: }
                   4580: /* }}} */
                   4581: 
                   4582: /* {{{ MBSTRING_API size_t php_mb_mbchar_bytes_ex() */
                   4583: MBSTRING_API size_t php_mb_mbchar_bytes_ex(const char *s, const mbfl_encoding *enc)
                   4584: {
                   4585:        if (enc != NULL) {
                   4586:                if (enc->flag & MBFL_ENCTYPE_MBCS) {
                   4587:                        if (enc->mblen_table != NULL) {
                   4588:                                if (s != NULL) return enc->mblen_table[*(unsigned char *)s];
                   4589:                        }
                   4590:                } else if (enc->flag & (MBFL_ENCTYPE_WCS2BE | MBFL_ENCTYPE_WCS2LE)) {
                   4591:                        return 2;
                   4592:                } else if (enc->flag & (MBFL_ENCTYPE_WCS4BE | MBFL_ENCTYPE_WCS4LE)) {
                   4593:                        return 4;
                   4594:                }
                   4595:        }
                   4596:        return 1;
                   4597: }
                   4598: /* }}} */
                   4599: 
                   4600: /* {{{ MBSTRING_API size_t php_mb_mbchar_bytes() */
                   4601: MBSTRING_API size_t php_mb_mbchar_bytes(const char *s TSRMLS_DC)
                   4602: {
1.1.1.2   misho    4603:        return php_mb_mbchar_bytes_ex(s, MBSTRG(internal_encoding));
1.1       misho    4604: }
                   4605: /* }}} */
                   4606: 
                   4607: /* {{{ MBSTRING_API char *php_mb_safe_strrchr_ex() */
                   4608: MBSTRING_API char *php_mb_safe_strrchr_ex(const char *s, unsigned int c, size_t nbytes, const mbfl_encoding *enc)
                   4609: {
                   4610:        register const char *p = s;
                   4611:        char *last=NULL;
                   4612: 
                   4613:        if (nbytes == (size_t)-1) {
                   4614:                size_t nb = 0;
                   4615: 
                   4616:                while (*p != '\0') {
                   4617:                        if (nb == 0) {
                   4618:                                if ((unsigned char)*p == (unsigned char)c) {
                   4619:                                        last = (char *)p;
                   4620:                                }
                   4621:                                nb = php_mb_mbchar_bytes_ex(p, enc);
                   4622:                                if (nb == 0) {
                   4623:                                        return NULL; /* something is going wrong! */
                   4624:                                }
                   4625:                        }
                   4626:                        --nb;
                   4627:                        ++p;
                   4628:                }
                   4629:        } else {
                   4630:                register size_t bcnt = nbytes;
                   4631:                register size_t nbytes_char;
                   4632:                while (bcnt > 0) {
                   4633:                        if ((unsigned char)*p == (unsigned char)c) {
                   4634:                                last = (char *)p;
                   4635:                        }
                   4636:                        nbytes_char = php_mb_mbchar_bytes_ex(p, enc);
                   4637:                        if (bcnt < nbytes_char) {
                   4638:                                return NULL;
                   4639:                        }
                   4640:                        p += nbytes_char;
                   4641:                        bcnt -= nbytes_char;
                   4642:                }
                   4643:        }
                   4644:        return last;
                   4645: }
                   4646: /* }}} */
                   4647: 
                   4648: /* {{{ MBSTRING_API char *php_mb_safe_strrchr() */
                   4649: MBSTRING_API char *php_mb_safe_strrchr(const char *s, unsigned int c, size_t nbytes TSRMLS_DC)
                   4650: {
1.1.1.2   misho    4651:        return php_mb_safe_strrchr_ex(s, c, nbytes, MBSTRG(internal_encoding));
1.1       misho    4652: }
                   4653: /* }}} */
                   4654: 
                   4655: /* {{{ MBSTRING_API int php_mb_stripos()
                   4656:  */
                   4657: MBSTRING_API int php_mb_stripos(int mode, const char *old_haystack, unsigned int old_haystack_len, const char *old_needle, unsigned int old_needle_len, long offset, const char *from_encoding TSRMLS_DC)
                   4658: {
                   4659:        int n;
                   4660:        mbfl_string haystack, needle;
                   4661:        n = -1;
                   4662: 
                   4663:        mbfl_string_init(&haystack);
                   4664:        mbfl_string_init(&needle);
                   4665:        haystack.no_language = MBSTRG(language);
1.1.1.2   misho    4666:        haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    4667:        needle.no_language = MBSTRG(language);
1.1.1.2   misho    4668:        needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
1.1       misho    4669: 
                   4670:        do {
                   4671:                size_t len = 0;
                   4672:                haystack.val = (unsigned char *)php_unicode_convert_case(PHP_UNICODE_CASE_UPPER, (char *)old_haystack, old_haystack_len, &len, from_encoding TSRMLS_CC);
                   4673:                haystack.len = len;
                   4674: 
                   4675:                if (!haystack.val) {
                   4676:                        break;
                   4677:                }
                   4678: 
                   4679:                if (haystack.len <= 0) {
                   4680:                        break;
                   4681:                }
                   4682: 
                   4683:                needle.val = (unsigned char *)php_unicode_convert_case(PHP_UNICODE_CASE_UPPER, (char *)old_needle, old_needle_len, &len, from_encoding TSRMLS_CC);
                   4684:                needle.len = len;
                   4685: 
                   4686:                if (!needle.val) {
                   4687:                        break;
                   4688:                }
                   4689: 
                   4690:                if (needle.len <= 0) {
                   4691:                        break;
                   4692:                }
                   4693: 
                   4694:                haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(from_encoding);
                   4695:                if (haystack.no_encoding == mbfl_no_encoding_invalid) {
                   4696:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", from_encoding);
                   4697:                        break;
                   4698:                }
                   4699: 
                   4700:                {
                   4701:                        int haystack_char_len = mbfl_strlen(&haystack);
                   4702:  
                   4703:                        if (mode) {
                   4704:                                if ((offset > 0 && offset > haystack_char_len) ||
                   4705:                                        (offset < 0 && -offset > haystack_char_len)) {
                   4706:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset is greater than the length of haystack string");
                   4707:                                        break;
                   4708:                                }
                   4709:                        } else {
                   4710:                                if (offset < 0 || offset > haystack_char_len) {
                   4711:                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset not contained in string");
                   4712:                                        break;
                   4713:                                }
                   4714:                        }
                   4715:                }
                   4716: 
                   4717:                n = mbfl_strpos(&haystack, &needle, offset, mode);
                   4718:        } while(0);
                   4719: 
                   4720:        if (haystack.val) {
                   4721:                efree(haystack.val);
                   4722:        }
                   4723: 
                   4724:        if (needle.val) {
                   4725:                efree(needle.val);
                   4726:        }
                   4727: 
                   4728:        return n;
                   4729: }
                   4730: /* }}} */
                   4731: 
1.1.1.2   misho    4732: static void php_mb_gpc_get_detect_order(const zend_encoding ***list, size_t *list_size TSRMLS_DC) /* {{{ */
1.1       misho    4733: {
1.1.1.2   misho    4734:        *list = (const zend_encoding **)MBSTRG(http_input_list);
                   4735:        *list_size = MBSTRG(http_input_list_size);
1.1       misho    4736: }
                   4737: /* }}} */
                   4738: 
1.1.1.2   misho    4739: static void php_mb_gpc_set_input_encoding(const zend_encoding *encoding TSRMLS_DC) /* {{{ */
1.1       misho    4740: {
1.1.1.2   misho    4741:        MBSTRG(http_input_identify) = (const mbfl_encoding*)encoding;
1.1       misho    4742: }
                   4743: /* }}} */
                   4744: 
                   4745: #endif /* HAVE_MBSTRING */
                   4746: 
                   4747: /*
                   4748:  * Local variables:
                   4749:  * tab-width: 4
                   4750:  * c-basic-offset: 4
                   4751:  * End:
                   4752:  * vim600: fdm=marker
                   4753:  * vim: noet sw=4 ts=4
                   4754:  */

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