PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/mbstring - mbstring.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 1691 2107 80.3 %
Date: 2014-09-21 Functions: 87 93 93.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 The PHP Group                                |
       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             : 
      20             : /* $Id$ */
      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"
      65             : #include "libmbfl/mbfl/mbfilter_pass.h"
      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             : 
     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             : 
     108             : /* }}} */
     109             : 
     110             : /* {{{ php_mb_default_identify_list */
     111             : typedef struct _php_mb_nls_ident_list {
     112             :         enum mbfl_no_language lang;
     113             :         const enum mbfl_no_encoding *list;
     114             :         size_t list_size;
     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)
     415             :         ZEND_ARG_INFO(0, is_hex)
     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             : 
     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             :  
     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 = {
     575             :         STANDARD_MODULE_HEADER,
     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),
     583             :         NO_VERSION_YET,
     584             :         PHP_MODULE_GLOBALS(mbstring),
     585             :         PHP_GINIT(mbstring),
     586             :         PHP_GSHUTDOWN(mbstring),
     587             :         NULL,
     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       74052 : static void *_php_mb_allocators_malloc(unsigned int sz)
     606             : {
     607       74052 :         return emalloc(sz);
     608             : }
     609             : 
     610       16536 : static void *_php_mb_allocators_realloc(void *ptr, unsigned int sz)
     611             : {
     612       16536 :         return erealloc(ptr, sz);
     613             : }
     614             : 
     615          52 : static void *_php_mb_allocators_calloc(unsigned int nelems, unsigned int szelem)
     616             : {
     617          52 :         return ecalloc(nelems, szelem);
     618             : }
     619             : 
     620       59236 : static void _php_mb_allocators_free(void *ptr)
     621             : {
     622       59236 :         efree(ptr);
     623       59236 : } 
     624             : 
     625           0 : static void *_php_mb_allocators_pmalloc(unsigned int sz)
     626             : {
     627           0 :         return pemalloc(sz, 1);
     628             : }
     629             : 
     630           0 : static void *_php_mb_allocators_prealloc(void *ptr, unsigned int sz)
     631             : {
     632           0 :         return perealloc(ptr, sz, 1);
     633             : }
     634             : 
     635           0 : static void _php_mb_allocators_pfree(void *ptr)
     636             : {
     637           0 :         pefree(ptr, 1);
     638           0 : } 
     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
     665      156651 : 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)
     666             : {
     667      156651 :         int size, bauto, ret = SUCCESS;
     668             :         size_t n;
     669             :         char *p, *p1, *p2, *endp, *tmpstr;
     670             :         const mbfl_encoding **entry, **list;
     671             : 
     672      156651 :         list = NULL;
     673      156651 :         if (value == NULL || value_length <= 0) {
     674       20212 :                 if (return_list) {
     675       20212 :                         *return_list = NULL;
     676             :                 }
     677       20212 :                 if (return_size) {
     678       20212 :                         *return_size = 0;
     679             :                 }
     680       20212 :                 return FAILURE;
     681             :         } else {
     682             :                 /* copy the value string for work */
     683      136439 :                 if (value[0]=='"' && value[value_length-1]=='"' && value_length>2) {
     684           0 :                         tmpstr = (char *)estrndup(value+1, value_length-2);
     685           0 :                         value_length -= 2;
     686             :                 }
     687             :                 else
     688      136439 :                         tmpstr = (char *)estrndup(value, value_length);
     689      136439 :                 if (tmpstr == NULL) {
     690           0 :                         return FAILURE;
     691             :                 }
     692             :                 /* count the number of listed encoding names */
     693      136439 :                 endp = tmpstr + value_length;
     694      136439 :                 n = 1;
     695      136439 :                 p1 = tmpstr;
     696      272908 :                 while ((p2 = php_memnstr(p1, ",", 1, endp)) != NULL) {
     697          30 :                         p1 = p2 + 1;
     698          30 :                         n++;
     699             :                 }
     700      136439 :                 size = n + MBSTRG(default_detect_order_list_size);
     701             :                 /* make list */
     702      136439 :                 list = (const mbfl_encoding **)pecalloc(size, sizeof(mbfl_encoding*), persistent);
     703      136439 :                 if (list != NULL) {
     704      136439 :                         entry = list;
     705      136439 :                         n = 0;
     706      136439 :                         bauto = 0;
     707      136439 :                         p1 = tmpstr;
     708             :                         do {
     709      136469 :                                 p2 = p = php_memnstr(p1, ",", 1, endp);
     710      136469 :                                 if (p == NULL) {
     711      136439 :                                         p = endp;
     712             :                                 }
     713      136469 :                                 *p = '\0';
     714             :                                 /* trim spaces */
     715      272938 :                                 while (p1 < p && (*p1 == ' ' || *p1 == '\t')) {
     716           0 :                                         p1++;
     717             :                                 }
     718      136469 :                                 p--;
     719      272938 :                                 while (p > p1 && (*p == ' ' || *p == '\t')) {
     720           0 :                                         *p = '\0';
     721           0 :                                         p--;
     722             :                                 }
     723             :                                 /* convert to the encoding number and check encoding */
     724      136469 :                                 if (strcasecmp(p1, "auto") == 0) {
     725          12 :                                         if (!bauto) {
     726          12 :                                                 const enum mbfl_no_encoding *src = MBSTRG(default_detect_order_list);
     727          12 :                                                 const size_t identify_list_size = MBSTRG(default_detect_order_list_size);
     728             :                                                 size_t i;
     729          12 :                                                 bauto = 1;
     730          69 :                                                 for (i = 0; i < identify_list_size; i++) {
     731          57 :                                                         *entry++ = mbfl_no2encoding(*src++);
     732          57 :                                                         n++;
     733             :                                                 }
     734             :                                         }
     735             :                                 } else {
     736      136457 :                                         const mbfl_encoding *encoding = mbfl_name2encoding(p1);
     737      136457 :                                         if (encoding) {
     738      136455 :                                                 *entry++ = encoding;
     739      136455 :                                                 n++;
     740             :                                         } else {
     741           2 :                                                 ret = 0;
     742             :                                         }
     743             :                                 }
     744      136469 :                                 p1 = p2 + 1;
     745      136469 :                         } while (n < size && p2 != NULL);
     746      136439 :                         if (n > 0) {
     747      136437 :                                 if (return_list) {
     748      136437 :                                         *return_list = list;
     749             :                                 } else {
     750           0 :                                         pefree(list, persistent);
     751             :                                 }
     752             :                         } else {
     753           2 :                                 pefree(list, persistent);
     754           2 :                                 if (return_list) {
     755           2 :                                         *return_list = NULL;
     756             :                                 }
     757           2 :                                 ret = 0;
     758             :                         }
     759      136439 :                         if (return_size) {
     760      136439 :                                 *return_size = n;
     761             :                         }
     762             :                 } else {
     763           0 :                         if (return_list) {
     764           0 :                                 *return_list = NULL;
     765             :                         }
     766           0 :                         if (return_size) {
     767           0 :                                 *return_size = 0;
     768             :                         }
     769           0 :                         ret = 0;
     770             :                 }
     771      136439 :                 efree(tmpstr);
     772             :         }
     773             : 
     774      136439 :         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
     784           5 : php_mb_parse_encoding_array(zval *array, const mbfl_encoding ***return_list, size_t *return_size, int persistent TSRMLS_DC)
     785             : {
     786             :         zval **hash_entry;
     787             :         HashTable *target_hash;
     788           5 :         int i, n, size, bauto, ret = SUCCESS;
     789             :         const mbfl_encoding **list, **entry;
     790             : 
     791           5 :         list = NULL;
     792           5 :         if (Z_TYPE_P(array) == IS_ARRAY) {
     793           5 :                 target_hash = Z_ARRVAL_P(array);
     794           5 :                 zend_hash_internal_pointer_reset(target_hash);
     795           5 :                 i = zend_hash_num_elements(target_hash);
     796           5 :                 size = i + MBSTRG(default_detect_order_list_size);
     797           5 :                 list = (const mbfl_encoding **)pecalloc(size, sizeof(mbfl_encoding*), persistent);
     798           5 :                 if (list != NULL) {
     799           5 :                         entry = list;
     800           5 :                         bauto = 0;
     801           5 :                         n = 0;
     802          31 :                         while (i > 0) {
     803          21 :                                 if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) {
     804           0 :                                         break;
     805             :                                 }
     806          21 :                                 convert_to_string_ex(hash_entry);
     807          21 :                                 if (strcasecmp(Z_STRVAL_PP(hash_entry), "auto") == 0) {
     808           0 :                                         if (!bauto) {
     809           0 :                                                 const enum mbfl_no_encoding *src = MBSTRG(default_detect_order_list);
     810           0 :                                                 const size_t identify_list_size = MBSTRG(default_detect_order_list_size);
     811             :                                                 size_t j;
     812             : 
     813           0 :                                                 bauto = 1;
     814           0 :                                                 for (j = 0; j < identify_list_size; j++) {
     815           0 :                                                         *entry++ = mbfl_no2encoding(*src++);
     816           0 :                                                         n++;
     817             :                                                 }
     818             :                                         }
     819             :                                 } else {
     820          21 :                                         const mbfl_encoding *encoding = mbfl_name2encoding(Z_STRVAL_PP(hash_entry));
     821          21 :                                         if (encoding) {
     822          20 :                                                 *entry++ = encoding;
     823          20 :                                                 n++;
     824             :                                         } else {
     825           1 :                                                 ret = FAILURE;
     826             :                                         }
     827             :                                 }
     828          21 :                                 zend_hash_move_forward(target_hash);
     829          21 :                                 i--;
     830             :                         }
     831           5 :                         if (n > 0) {
     832           5 :                                 if (return_list) {
     833           5 :                                         *return_list = list;
     834             :                                 } else {
     835           0 :                                         pefree(list, persistent);
     836             :                                 }
     837             :                         } else {
     838           0 :                                 pefree(list, persistent);
     839           0 :                                 if (return_list) {
     840           0 :                                         *return_list = NULL;
     841             :                                 }
     842           0 :                                 ret = FAILURE;
     843             :                         }
     844           5 :                         if (return_size) {
     845           5 :                                 *return_size = n;
     846             :                         }
     847             :                 } else {
     848           0 :                         if (return_list) {
     849           0 :                                 *return_list = NULL;
     850             :                         }
     851           0 :                         if (return_size) {
     852           0 :                                 *return_size = 0;
     853             :                         }
     854           0 :                         ret = FAILURE;
     855             :                 }
     856             :         }
     857             : 
     858           5 :         return ret;
     859             : }
     860             : /* }}} */
     861             : 
     862             : /* {{{ zend_multibyte interface */
     863      101156 : static const zend_encoding* php_mb_zend_encoding_fetcher(const char *encoding_name TSRMLS_DC)
     864             : {
     865      101156 :         return (const zend_encoding*)mbfl_name2encoding(encoding_name);
     866             : }
     867             : 
     868          18 : static const char *php_mb_zend_encoding_name_getter(const zend_encoding *encoding)
     869             : {
     870          18 :         return ((const mbfl_encoding *)encoding)->name;
     871             : }
     872             : 
     873          52 : static int php_mb_zend_encoding_lexer_compatibility_checker(const zend_encoding *_encoding)
     874             : {
     875          52 :         const mbfl_encoding *encoding = (const mbfl_encoding*)_encoding;
     876          52 :         if (encoding->flag & MBFL_ENCTYPE_SBCS) {
     877          25 :                 return 1;
     878             :         }
     879          27 :         if ((encoding->flag & (MBFL_ENCTYPE_MBCS | MBFL_ENCTYPE_GL_UNSAFE)) == MBFL_ENCTYPE_MBCS) {
     880          23 :                 return 1;
     881             :         }
     882           4 :         return 0;
     883             : }
     884             : 
     885           3 : 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           3 :         if (!list) {
     890           0 :                 list = (const zend_encoding **)MBSTRG(current_detect_order_list);
     891           0 :                 list_size = MBSTRG(current_detect_order_list_size);
     892             :         }
     893             : 
     894           3 :         mbfl_string_init(&string);
     895           3 :         string.no_language = MBSTRG(language);
     896           3 :         string.val = (unsigned char *)arg_string;
     897           3 :         string.len = arg_length;
     898           3 :         return (const zend_encoding *) mbfl_identify_encoding2(&string, (const mbfl_encoding **)list, list_size, 0);
     899             : }
     900             : 
     901          68 : 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          68 :         mbfl_string_init(&string);
     910          68 :         mbfl_string_init(&result);
     911          68 :         string.no_encoding = ((const mbfl_encoding*)encoding_from)->no_encoding;
     912          68 :         string.no_language = MBSTRG(language);
     913          68 :         string.val = (unsigned char*)from;
     914          68 :         string.len = from_length;
     915             : 
     916             :         /* initialize converter */
     917          68 :         convd = mbfl_buffer_converter_new2((const mbfl_encoding *)encoding_from, (const mbfl_encoding *)encoding_to, string.len);
     918          68 :         if (convd == NULL) {
     919           0 :                 return -1;
     920             :         }
     921          68 :         mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
     922          68 :         mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
     923             : 
     924             :         /* do it */
     925          68 :         status = mbfl_buffer_converter_feed2(convd, &string, &loc);
     926          68 :         if (status) {
     927           0 :                 mbfl_buffer_converter_delete(convd);
     928           0 :                 return (size_t)-1;
     929             :         }
     930             : 
     931          68 :         mbfl_buffer_converter_flush(convd);
     932          68 :         if (!mbfl_buffer_converter_result(convd, &result)) {
     933           0 :                 mbfl_buffer_converter_delete(convd);
     934           0 :                 return (size_t)-1;
     935             :         }       
     936             : 
     937          68 :         *to = result.val;
     938          68 :         *to_length = result.len;
     939             : 
     940          68 :         mbfl_buffer_converter_delete(convd);
     941             : 
     942          68 :         return loc;
     943             : }
     944             : 
     945      121350 : 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      121350 :         return php_mb_parse_encoding_list(encoding_list, encoding_list_len, (const mbfl_encoding ***)return_list, return_size, persistent TSRMLS_CC);
     948             : }
     949             : 
     950         120 : static const zend_encoding *php_mb_zend_internal_encoding_getter(TSRMLS_D)
     951             : {
     952         120 :         return (const zend_encoding *)MBSTRG(internal_encoding);
     953             : }
     954             : 
     955       20182 : static int php_mb_zend_internal_encoding_setter(const zend_encoding *encoding TSRMLS_DC)
     956             : {
     957       20182 :         MBSTRG(internal_encoding) = (const mbfl_encoding *)encoding;
     958       20182 :         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             : 
     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       20229 : 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       40458 :         if ((err_code = onig_new(&retval,
     987             :                         (const OnigUChar *)pattern,
     988       20229 :                         (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           0 :                 onig_error_code_to_str(err_str, err_code, err_info);
     993           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %s", pattern, err_str);
     994           0 :                 retval = NULL;
     995             :         }
     996       20229 :         return retval;
     997             : }
     998             : /* }}} */
     999             : 
    1000             : /* {{{ _php_mb_match_regex */
    1001          12 : static int _php_mb_match_regex(void *opaque, const char *str, size_t str_len)
    1002             : {
    1003          12 :         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       20265 : static void _php_mb_free_regex(void *opaque)
    1011             : {
    1012       20265 :         onig_free((php_mb_regex_t *)opaque);
    1013       20265 : }
    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 */
    1048       20255 : static int php_mb_nls_get_default_detect_order_list(enum mbfl_no_language lang, enum mbfl_no_encoding **plist, size_t *plist_size)
    1049             : {
    1050             :         size_t i;
    1051             : 
    1052       20255 :         *plist = (enum mbfl_no_encoding *) php_mb_default_identify_list_neut;
    1053       20255 :         *plist_size = sizeof(php_mb_default_identify_list_neut) / sizeof(php_mb_default_identify_list_neut[0]);
    1054             : 
    1055      182121 :         for (i = 0; i < sizeof(php_mb_default_identify_list) / sizeof(php_mb_default_identify_list[0]); i++) {
    1056      182117 :                 if (php_mb_default_identify_list[i].lang == lang) {
    1057       20251 :                         *plist = (enum mbfl_no_encoding *)php_mb_default_identify_list[i].list;
    1058       20251 :                         *plist_size = php_mb_default_identify_list[i].list_size;
    1059       20251 :                         return 1;
    1060             :                 }
    1061             :         }
    1062           4 :         return 0;
    1063             : }
    1064             : /* }}} */
    1065             : 
    1066           3 : static char *php_mb_rfc1867_substring_conf(const zend_encoding *encoding, char *start, int len, char quote TSRMLS_DC)
    1067             : {
    1068           3 :         char *result = emalloc(len + 2);
    1069           3 :         char *resp = result;
    1070             :         int i;
    1071             : 
    1072          19 :         for (i = 0; i < len && start[i] != quote; ++i) {
    1073          16 :                 if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
    1074           0 :                         *resp++ = start[++i];
    1075             :                 } else {
    1076          16 :                         size_t j = php_mb_mbchar_bytes_ex(start+i, (const mbfl_encoding *)encoding);
    1077             : 
    1078          51 :                         while (j-- > 0 && i < len) {
    1079          19 :                                 *resp++ = start[i++];
    1080             :                         }
    1081          16 :                         --i;
    1082             :                 }
    1083             :         }
    1084             : 
    1085           3 :         *resp = '\0';
    1086           3 :         return result;
    1087             : }
    1088             : 
    1089           8 : static char *php_mb_rfc1867_getword(const zend_encoding *encoding, char **line, char stop TSRMLS_DC) /* {{{ */
    1090             : {
    1091           8 :         char *pos = *line, quote;
    1092             :         char *res;
    1093             : 
    1094          72 :         while (*pos && *pos != stop) {
    1095          59 :                 if ((quote = *pos) == '"' || quote == '\'') {
    1096           3 :                         ++pos;
    1097          25 :                         while (*pos && *pos != quote) {
    1098          20 :                                 if (*pos == '\\' && pos[1] && pos[1] == quote) {
    1099           1 :                                         pos += 2;
    1100             :                                 } else {
    1101          18 :                                         ++pos;
    1102             :                                 }
    1103             :                         }
    1104           3 :                         if (*pos) {
    1105           2 :                                 ++pos;
    1106             :                         }
    1107             :                 } else {
    1108          53 :                         pos += php_mb_mbchar_bytes_ex(pos, (const mbfl_encoding *)encoding);
    1109             : 
    1110             :                 }
    1111             :         }
    1112           8 :         if (*pos == '\0') {
    1113           2 :                 res = estrdup(*line);
    1114           2 :                 *line += strlen(*line);
    1115           2 :                 return res;
    1116             :         }
    1117             : 
    1118           6 :         res = estrndup(*line, pos - *line);
    1119             : 
    1120          18 :         while (*pos == stop) {
    1121           6 :                 pos += php_mb_mbchar_bytes_ex(pos, (const mbfl_encoding *)encoding);
    1122             :         }
    1123             : 
    1124           6 :         *line = pos;
    1125           6 :         return res;
    1126             : }
    1127             : /* }}} */
    1128             : 
    1129           3 : static char *php_mb_rfc1867_getword_conf(const zend_encoding *encoding, char *str TSRMLS_DC) /* {{{ */
    1130             : {
    1131           6 :         while (*str && isspace(*(unsigned char *)str)) {
    1132           0 :                 ++str;
    1133             :         }
    1134             : 
    1135           3 :         if (!*str) {
    1136           0 :                 return estrdup("");
    1137             :         }
    1138             : 
    1139           3 :         if (*str == '"' || *str == '\'') {
    1140           3 :                 char quote = *str;
    1141             : 
    1142           3 :                 str++;
    1143           3 :                 return php_mb_rfc1867_substring_conf(encoding, str, strlen(str), quote TSRMLS_CC);
    1144             :         } else {
    1145           0 :                 char *strend = str;
    1146             : 
    1147           0 :                 while (*strend && !isspace(*(unsigned char *)strend)) {
    1148           0 :                         ++strend;
    1149             :                 }
    1150           0 :                 return php_mb_rfc1867_substring_conf(encoding, str, strend - str, 0 TSRMLS_CC);
    1151             :         }
    1152             : }
    1153             : /* }}} */
    1154             : 
    1155           1 : static char *php_mb_rfc1867_basename(const zend_encoding *encoding, char *filename TSRMLS_DC) /* {{{ */
    1156             : {
    1157             :         char *s, *s2;
    1158           1 :         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           1 :         s = php_mb_safe_strrchr_ex(filename, '\\', filename_len, (const mbfl_encoding *)encoding);
    1166           1 :         s2 = php_mb_safe_strrchr_ex(filename, '/', filename_len, (const mbfl_encoding *)encoding);
    1167             :         
    1168           1 :         if (s && s2) {
    1169           0 :                 if (s > s2) {
    1170           0 :                         return ++s;
    1171             :                 } else {
    1172           0 :                         return ++s2;
    1173             :                 }
    1174           1 :         } else if (s) {
    1175           0 :                 return ++s;
    1176           1 :         } else if (s2) {
    1177           0 :                 return ++s2;
    1178             :         } else {
    1179           1 :                 return filename;
    1180             :         }
    1181             : }
    1182             : /* }}} */
    1183             : 
    1184             : /* {{{ php.ini directive handler */
    1185             : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_language) */
    1186       20255 : static PHP_INI_MH(OnUpdate_mbstring_language)
    1187             : {
    1188             :         enum mbfl_no_language no_language;
    1189             : 
    1190       20255 :         no_language = mbfl_name2no_language(new_value);
    1191       20255 :         if (no_language == mbfl_no_language_invalid) {
    1192           0 :                 MBSTRG(language) = mbfl_no_language_neutral;
    1193           0 :                 return FAILURE;
    1194             :         }
    1195       20255 :         MBSTRG(language) = no_language;
    1196       20255 :         php_mb_nls_get_default_detect_order_list(no_language, &MBSTRG(default_detect_order_list), &MBSTRG(default_detect_order_list_size));
    1197       20255 :         return SUCCESS;
    1198             : }
    1199             : /* }}} */
    1200             : 
    1201             : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_detect_order) */
    1202       20225 : static PHP_INI_MH(OnUpdate_mbstring_detect_order)
    1203             : {
    1204             :         const mbfl_encoding **list;
    1205             :         size_t size;
    1206             : 
    1207       20225 :         if (!new_value) {
    1208       20223 :                 if (MBSTRG(detect_order_list)) {
    1209           0 :                         pefree(MBSTRG(detect_order_list), 1);
    1210             :                 }
    1211       20223 :                 MBSTRG(detect_order_list) = NULL;
    1212       20223 :                 MBSTRG(detect_order_list_size) = 0;
    1213       20223 :                 return SUCCESS;
    1214             :         }
    1215             : 
    1216           2 :         if (FAILURE == php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
    1217           0 :                 return FAILURE;
    1218             :         }
    1219             : 
    1220           2 :         if (MBSTRG(detect_order_list)) {
    1221           0 :                 pefree(MBSTRG(detect_order_list), 1);
    1222             :         }
    1223           2 :         MBSTRG(detect_order_list) = list;
    1224           2 :         MBSTRG(detect_order_list_size) = size;
    1225           2 :         return SUCCESS;
    1226             : }
    1227             : /* }}} */
    1228             : 
    1229             : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_http_input) */
    1230       20225 : static PHP_INI_MH(OnUpdate_mbstring_http_input)
    1231             : {
    1232             :         const mbfl_encoding **list;
    1233             :         size_t size;
    1234             : 
    1235       20225 :         if (!new_value) {
    1236           0 :                 if (MBSTRG(http_input_list)) {
    1237           0 :                         pefree(MBSTRG(http_input_list), 1);
    1238             :                 }
    1239           0 :                 MBSTRG(http_input_list) = NULL;
    1240           0 :                 MBSTRG(http_input_list_size) = 0;
    1241           0 :                 return SUCCESS;
    1242             :         }
    1243             : 
    1244       20225 :         if (FAILURE == php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, 1 TSRMLS_CC)) {
    1245           0 :                 return FAILURE;
    1246             :         }
    1247             : 
    1248       20225 :         if (MBSTRG(http_input_list)) {
    1249           0 :                 pefree(MBSTRG(http_input_list), 1);
    1250             :         }
    1251       20225 :         MBSTRG(http_input_list) = list;
    1252       20225 :         MBSTRG(http_input_list_size) = size;
    1253             : 
    1254       20225 :         return SUCCESS;
    1255             : }
    1256             : /* }}} */
    1257             : 
    1258             : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_http_output) */
    1259       20225 : static PHP_INI_MH(OnUpdate_mbstring_http_output)
    1260             : {
    1261             :         const mbfl_encoding *encoding;
    1262             : 
    1263       20225 :         if (new_value == NULL || new_value_length == 0) {
    1264           0 :                 MBSTRG(http_output_encoding) = &mbfl_encoding_pass;
    1265           0 :                 MBSTRG(current_http_output_encoding) = &mbfl_encoding_pass;
    1266           0 :                 return SUCCESS;
    1267             :         }
    1268             : 
    1269       20225 :         encoding = mbfl_name2encoding(new_value);
    1270       20225 :         if (!encoding) {
    1271           0 :                 MBSTRG(http_output_encoding) = &mbfl_encoding_pass;
    1272           0 :                 MBSTRG(current_http_output_encoding) = &mbfl_encoding_pass;
    1273           0 :                 return FAILURE;
    1274             :         }
    1275             : 
    1276       20225 :         MBSTRG(http_output_encoding) = encoding;
    1277       20225 :         MBSTRG(current_http_output_encoding) = encoding;
    1278       20225 :         return SUCCESS;
    1279             : }
    1280             : /* }}} */
    1281             : 
    1282             : /* {{{ static _php_mb_ini_mbstring_internal_encoding_set */
    1283       60670 : int _php_mb_ini_mbstring_internal_encoding_set(const char *new_value, uint new_value_length TSRMLS_DC)
    1284             : {
    1285             :         const mbfl_encoding *encoding;
    1286             : 
    1287       60670 :         if (!new_value || new_value_length == 0 || !(encoding = mbfl_name2encoding(new_value))) {
    1288       60365 :                 switch (MBSTRG(language)) {
    1289             :                         case mbfl_no_language_uni:
    1290           0 :                                 encoding = mbfl_no2encoding(mbfl_no_encoding_utf8);
    1291           0 :                                 break;
    1292             :                         case mbfl_no_language_japanese:
    1293          30 :                                 encoding = mbfl_no2encoding(mbfl_no_encoding_euc_jp);
    1294          30 :                                 break;
    1295             :                         case mbfl_no_language_korean:
    1296           0 :                                 encoding = mbfl_no2encoding(mbfl_no_encoding_euc_kr);
    1297           0 :                                 break;
    1298             :                         case mbfl_no_language_simplified_chinese:
    1299           0 :                                 encoding = mbfl_no2encoding(mbfl_no_encoding_euc_cn);
    1300           0 :                                 break;
    1301             :                         case mbfl_no_language_traditional_chinese:
    1302           0 :                                 encoding = mbfl_no2encoding(mbfl_no_encoding_euc_tw);
    1303           0 :                                 break;
    1304             :                         case mbfl_no_language_russian:
    1305           0 :                                 encoding = mbfl_no2encoding(mbfl_no_encoding_koi8r);
    1306           0 :                                 break;
    1307             :                         case mbfl_no_language_german:
    1308           0 :                                 encoding = mbfl_no2encoding(mbfl_no_encoding_8859_15);
    1309           0 :                                 break;
    1310             :                         case mbfl_no_language_armenian:
    1311           0 :                                 encoding = mbfl_no2encoding(mbfl_no_encoding_armscii8);
    1312           0 :                                 break;
    1313             :                         case mbfl_no_language_turkish:
    1314           0 :                                 encoding = mbfl_no2encoding(mbfl_no_encoding_8859_9);
    1315           0 :                                 break;
    1316             :                         default:
    1317       60335 :                                 encoding = mbfl_no2encoding(mbfl_no_encoding_8859_1);
    1318             :                                 break;
    1319             :                 }
    1320             :         }
    1321       60670 :         MBSTRG(internal_encoding) = encoding;
    1322       60670 :         MBSTRG(current_internal_encoding) = encoding;
    1323             : #if HAVE_MBREGEX
    1324             :         {
    1325       60670 :                 const char *enc_name = new_value;
    1326       60670 :                 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       60419 :                         enc_name = "EUC-JP";
    1329       60419 :                         php_mb_regex_set_default_mbctype(enc_name TSRMLS_CC);
    1330             :                 }
    1331       60670 :                 php_mb_regex_set_mbctype(new_value TSRMLS_CC);
    1332             :         }
    1333             : #endif
    1334       60670 :         return SUCCESS;
    1335             : }
    1336             : /* }}} */
    1337             : 
    1338             : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_internal_encoding) */
    1339       20227 : static PHP_INI_MH(OnUpdate_mbstring_internal_encoding)
    1340             : {
    1341       20227 :         if (OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC) == FAILURE) {
    1342           0 :                 return FAILURE;
    1343             :         }
    1344       20227 :         if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN
    1345             :                         || stage == PHP_INI_STAGE_RUNTIME) {
    1346       20226 :                 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           1 :                 return SUCCESS;
    1355             :         }
    1356             : }
    1357             : /* }}} */
    1358             : 
    1359             : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_substitute_character) */
    1360       20225 : static PHP_INI_MH(OnUpdate_mbstring_substitute_character)
    1361             : {
    1362             :         int c;
    1363       20225 :         char *endptr = NULL;
    1364             : 
    1365       20225 :         if (new_value != NULL) {
    1366           2 :                 if (strcasecmp("none", new_value) == 0) {
    1367           0 :                         MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE;
    1368           0 :                         MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE;
    1369           2 :                 } else if (strcasecmp("long", new_value) == 0) {
    1370           0 :                         MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG;
    1371           0 :                         MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG;
    1372           2 :                 } else if (strcasecmp("entity", new_value) == 0) {
    1373           0 :                         MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY;
    1374           0 :                         MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY;
    1375             :                 } else {
    1376           2 :                         MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
    1377           2 :                         MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
    1378           2 :                         if (new_value_length >0) {
    1379           2 :                                 c = strtol(new_value, &endptr, 0);
    1380           2 :                                 if (*endptr == '\0') {
    1381           2 :                                         MBSTRG(filter_illegal_substchar) = c;
    1382           2 :                                         MBSTRG(current_filter_illegal_substchar) = c;
    1383             :                                 }
    1384             :                         }
    1385             :                 }
    1386             :         } else {
    1387       20223 :                 MBSTRG(filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
    1388       20223 :                 MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
    1389       20223 :                 MBSTRG(filter_illegal_substchar) = 0x3f;        /* '?' */
    1390       20223 :                 MBSTRG(current_filter_illegal_substchar) = 0x3f;        /* '?' */
    1391             :         }
    1392             : 
    1393       20225 :         return SUCCESS;
    1394             : }
    1395             : /* }}} */
    1396             : 
    1397             : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_encoding_translation) */
    1398       20225 : static PHP_INI_MH(OnUpdate_mbstring_encoding_translation)
    1399             : {
    1400       20225 :         if (new_value == NULL) {
    1401           0 :                 return FAILURE;
    1402             :         }
    1403             : 
    1404       20225 :         OnUpdateBool(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
    1405             : 
    1406       20225 :         if (MBSTRG(encoding_translation)) {
    1407          14 :                 sapi_unregister_post_entry(php_post_entries TSRMLS_CC);
    1408          14 :                 sapi_register_post_entries(mbstr_post_entries TSRMLS_CC);
    1409             :         } else {
    1410       20211 :                 sapi_unregister_post_entry(mbstr_post_entries TSRMLS_CC);
    1411       20211 :                 sapi_register_post_entries(php_post_entries TSRMLS_CC);
    1412             :         }
    1413             : 
    1414       20225 :         return SUCCESS;
    1415             : }
    1416             : /* }}} */
    1417             : 
    1418             : /* {{{ static PHP_INI_MH(OnUpdate_mbstring_http_output_conv_mimetypes */
    1419       20229 : static PHP_INI_MH(OnUpdate_mbstring_http_output_conv_mimetypes)
    1420             : {
    1421             :         zval tmp;
    1422       20229 :         void *re = NULL;
    1423             : 
    1424       20229 :         if (!new_value) {
    1425           0 :                 new_value = entry->orig_value;
    1426           0 :                 new_value_length = entry->orig_value_length;
    1427             :         }
    1428       20229 :         php_trim(new_value, new_value_length, NULL, 0, &tmp, 3 TSRMLS_CC);
    1429             : 
    1430       20229 :         if (Z_STRLEN(tmp) > 0) {
    1431       20229 :                 if (!(re = _php_mb_compile_regex(Z_STRVAL(tmp) TSRMLS_CC))) {
    1432             :                         zval_dtor(&tmp);
    1433           0 :                         return FAILURE;
    1434             :                 }
    1435             :         }
    1436             : 
    1437       20229 :         if (MBSTRG(http_output_conv_mimetypes)) {
    1438           4 :                 _php_mb_free_regex(MBSTRG(http_output_conv_mimetypes));
    1439             :         }
    1440             : 
    1441       20229 :         MBSTRG(http_output_conv_mimetypes) = re;
    1442             : 
    1443             :         zval_dtor(&tmp);
    1444       20229 :         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)
    1455             :         STD_PHP_INI_ENTRY("mbstring.internal_encoding", NULL, PHP_INI_ALL, OnUpdate_mbstring_internal_encoding, internal_encoding_name, zend_mbstring_globals, mbstring_globals)
    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       20225 : static PHP_GINIT_FUNCTION(mbstring)
    1478             : {
    1479       20225 :         mbstring_globals->language = mbfl_no_language_uni;
    1480       20225 :         mbstring_globals->internal_encoding = NULL;
    1481       20225 :         mbstring_globals->current_internal_encoding = mbstring_globals->internal_encoding;
    1482       20225 :         mbstring_globals->http_output_encoding = &mbfl_encoding_pass;
    1483       20225 :         mbstring_globals->current_http_output_encoding = &mbfl_encoding_pass;
    1484       20225 :         mbstring_globals->http_input_identify = NULL;
    1485       20225 :         mbstring_globals->http_input_identify_get = NULL;
    1486       20225 :         mbstring_globals->http_input_identify_post = NULL;
    1487       20225 :         mbstring_globals->http_input_identify_cookie = NULL;
    1488       20225 :         mbstring_globals->http_input_identify_string = NULL;
    1489       20225 :         mbstring_globals->http_input_list = NULL;
    1490       20225 :         mbstring_globals->http_input_list_size = 0;
    1491       20225 :         mbstring_globals->detect_order_list = NULL;
    1492       20225 :         mbstring_globals->detect_order_list_size = 0;
    1493       20225 :         mbstring_globals->current_detect_order_list = NULL;
    1494       20225 :         mbstring_globals->current_detect_order_list_size = 0;
    1495       20225 :         mbstring_globals->default_detect_order_list = (enum mbfl_no_encoding *) php_mb_default_identify_list_neut;
    1496       20225 :         mbstring_globals->default_detect_order_list_size = sizeof(php_mb_default_identify_list_neut) / sizeof(php_mb_default_identify_list_neut[0]);
    1497       20225 :         mbstring_globals->filter_illegal_mode = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
    1498       20225 :         mbstring_globals->filter_illegal_substchar = 0x3f;   /* '?' */
    1499       20225 :         mbstring_globals->current_filter_illegal_mode = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
    1500       20225 :         mbstring_globals->current_filter_illegal_substchar = 0x3f;   /* '?' */
    1501       20225 :         mbstring_globals->illegalchars = 0;
    1502       20225 :         mbstring_globals->func_overload = 0;
    1503       20225 :         mbstring_globals->encoding_translation = 0;
    1504       20225 :         mbstring_globals->strict_detection = 0;
    1505       20225 :         mbstring_globals->outconv = NULL;
    1506       20225 :         mbstring_globals->http_output_conv_mimetypes = NULL;
    1507             : #if HAVE_MBREGEX
    1508       20225 :         mbstring_globals->mb_regex_globals = php_mb_regex_globals_alloc(TSRMLS_C);
    1509             : #endif
    1510       20225 : }
    1511             : /* }}} */
    1512             : 
    1513             : /* {{{ PHP_GSHUTDOWN_FUNCTION */
    1514       20261 : static PHP_GSHUTDOWN_FUNCTION(mbstring)
    1515             : {
    1516       20261 :         if (mbstring_globals->http_input_list) {
    1517       20261 :                 free(mbstring_globals->http_input_list);
    1518             :         }
    1519       20261 :         if (mbstring_globals->detect_order_list) {
    1520           2 :                 free(mbstring_globals->detect_order_list);
    1521             :         }
    1522       20261 :         if (mbstring_globals->http_output_conv_mimetypes) {
    1523       20261 :                 _php_mb_free_regex(mbstring_globals->http_output_conv_mimetypes);
    1524             :         }
    1525             : #if HAVE_MBREGEX
    1526       20261 :         php_mb_regex_globals_free(mbstring_globals->mb_regex_globals TSRMLS_CC);
    1527             : #endif
    1528       20261 : }
    1529             : /* }}} */
    1530             : 
    1531             : /* {{{ PHP_MINIT_FUNCTION(mbstring) */
    1532       20225 : PHP_MINIT_FUNCTION(mbstring)
    1533             : {
    1534       20225 :         __mbfl_allocators = &_php_mb_allocators;
    1535             : 
    1536       20225 :         REGISTER_INI_ENTRIES();
    1537             : 
    1538             :         /* This is a global handler. Should not be set in a per-request handler. */
    1539       20225 :         sapi_register_treat_data(mbstr_treat_data TSRMLS_CC);
    1540             : 
    1541             :         /* Post handlers are stored in the thread-local context. */
    1542       20225 :         if (MBSTRG(encoding_translation)) {
    1543          14 :                 sapi_register_post_entries(mbstr_post_entries TSRMLS_CC);
    1544             :         }
    1545             : 
    1546       20225 :         REGISTER_LONG_CONSTANT("MB_OVERLOAD_MAIL", MB_OVERLOAD_MAIL, CONST_CS | CONST_PERSISTENT);
    1547       20225 :         REGISTER_LONG_CONSTANT("MB_OVERLOAD_STRING", MB_OVERLOAD_STRING, CONST_CS | CONST_PERSISTENT);
    1548       20225 :         REGISTER_LONG_CONSTANT("MB_OVERLOAD_REGEX", MB_OVERLOAD_REGEX, CONST_CS | CONST_PERSISTENT);
    1549             : 
    1550       20225 :         REGISTER_LONG_CONSTANT("MB_CASE_UPPER", PHP_UNICODE_CASE_UPPER, CONST_CS | CONST_PERSISTENT);
    1551       20225 :         REGISTER_LONG_CONSTANT("MB_CASE_LOWER", PHP_UNICODE_CASE_LOWER, CONST_CS | CONST_PERSISTENT);
    1552       20225 :         REGISTER_LONG_CONSTANT("MB_CASE_TITLE", PHP_UNICODE_CASE_TITLE, CONST_CS | CONST_PERSISTENT);
    1553             : 
    1554             : #if HAVE_MBREGEX
    1555       20225 :         PHP_MINIT(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
    1556             : #endif
    1557             : 
    1558       20225 :         if (FAILURE == zend_multibyte_set_functions(&php_mb_zend_multibyte_functions TSRMLS_CC)) {
    1559           0 :                 return FAILURE;
    1560             :         }
    1561             : 
    1562       20225 :         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             : 
    1570       20225 :         return SUCCESS;
    1571             : }
    1572             : /* }}} */
    1573             : 
    1574             : /* {{{ PHP_MSHUTDOWN_FUNCTION(mbstring) */
    1575       20261 : PHP_MSHUTDOWN_FUNCTION(mbstring)
    1576             : {
    1577       20261 :         UNREGISTER_INI_ENTRIES();
    1578             : 
    1579             : #if HAVE_MBREGEX
    1580       20261 :         PHP_MSHUTDOWN(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
    1581             : #endif
    1582             : 
    1583       20261 :         return SUCCESS;
    1584             : }
    1585             : /* }}} */
    1586             : 
    1587             : /* {{{ PHP_RINIT_FUNCTION(mbstring) */
    1588       20182 : PHP_RINIT_FUNCTION(mbstring)
    1589             : {
    1590             :         zend_function *func, *orig;
    1591             :         const struct mb_overload_def *p;
    1592             : 
    1593       20182 :         MBSTRG(current_internal_encoding) = MBSTRG(internal_encoding);
    1594       20182 :         MBSTRG(current_http_output_encoding) = MBSTRG(http_output_encoding);
    1595       20182 :         MBSTRG(current_filter_illegal_mode) = MBSTRG(filter_illegal_mode);
    1596       20182 :         MBSTRG(current_filter_illegal_substchar) = MBSTRG(filter_illegal_substchar);
    1597             : 
    1598       20182 :         MBSTRG(illegalchars) = 0;
    1599             : 
    1600       20182 :         php_mb_populate_current_detect_order_list(TSRMLS_C);
    1601             : 
    1602             :         /* override original function. */
    1603       20182 :         if (MBSTRG(func_overload)){
    1604           8 :                 p = &(mb_ovld[0]);
    1605             :                 
    1606         160 :                 while (p->type > 0) {
    1607         276 :                         if ((MBSTRG(func_overload) & p->type) == p->type && 
    1608         132 :                                 zend_hash_find(EG(function_table), p->save_func,
    1609         264 :                                         strlen(p->save_func)+1, (void **)&orig) != SUCCESS) {
    1610             : 
    1611         132 :                                 zend_hash_find(EG(function_table), p->ovld_func, strlen(p->ovld_func)+1 , (void **)&func);
    1612             :                                 
    1613         132 :                                 if (zend_hash_find(EG(function_table), p->orig_func, strlen(p->orig_func)+1, (void **)&orig) != SUCCESS) {
    1614           0 :                                         php_error_docref("ref.mbstring" TSRMLS_CC, E_WARNING, "mbstring couldn't find function %s.", p->orig_func);
    1615           0 :                                         return FAILURE;
    1616             :                                 } else {
    1617         132 :                                         zend_hash_add(EG(function_table), p->save_func, strlen(p->save_func)+1, orig, sizeof(zend_function), NULL);
    1618             : 
    1619         132 :                                         if (zend_hash_update(EG(function_table), p->orig_func, strlen(p->orig_func)+1, func, sizeof(zend_function), 
    1620             :                                                 NULL) == FAILURE) {
    1621           0 :                                                 php_error_docref("ref.mbstring" TSRMLS_CC, E_WARNING, "mbstring couldn't replace function %s.", p->orig_func);
    1622           0 :                                                 return FAILURE;
    1623             :                                         }
    1624             :                                 }
    1625             :                         }
    1626         144 :                         p++;
    1627             :                 }
    1628             :         }
    1629             : #if HAVE_MBREGEX
    1630       20182 :         PHP_RINIT(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
    1631             : #endif
    1632       20182 :         zend_multibyte_set_internal_encoding((const zend_encoding *)MBSTRG(internal_encoding) TSRMLS_CC);
    1633             : 
    1634       20182 :         return SUCCESS;
    1635             : }
    1636             : /* }}} */
    1637             : 
    1638             : /* {{{ PHP_RSHUTDOWN_FUNCTION(mbstring) */
    1639       20220 : PHP_RSHUTDOWN_FUNCTION(mbstring)
    1640             : {
    1641             :         const struct mb_overload_def *p;
    1642             :         zend_function *orig;
    1643             : 
    1644       20220 :         if (MBSTRG(current_detect_order_list) != NULL) {
    1645       20220 :                 efree(MBSTRG(current_detect_order_list));
    1646       20220 :                 MBSTRG(current_detect_order_list) = NULL;
    1647       20220 :                 MBSTRG(current_detect_order_list_size) = 0;
    1648             :         }
    1649       20220 :         if (MBSTRG(outconv) != NULL) {
    1650           0 :                 MBSTRG(illegalchars) += mbfl_buffer_illegalchars(MBSTRG(outconv));
    1651           0 :                 mbfl_buffer_converter_delete(MBSTRG(outconv));
    1652           0 :                 MBSTRG(outconv) = NULL;
    1653             :         }
    1654             : 
    1655             :         /* clear http input identification. */
    1656       20220 :         MBSTRG(http_input_identify) = NULL;
    1657       20220 :         MBSTRG(http_input_identify_post) = NULL;
    1658       20220 :         MBSTRG(http_input_identify_get) = NULL;
    1659       20220 :         MBSTRG(http_input_identify_cookie) = NULL;
    1660       20220 :         MBSTRG(http_input_identify_string) = NULL;
    1661             : 
    1662             :         /*  clear overloaded function. */
    1663       20220 :         if (MBSTRG(func_overload)){
    1664           8 :                 p = &(mb_ovld[0]);
    1665         160 :                 while (p->type > 0) {
    1666         276 :                         if ((MBSTRG(func_overload) & p->type) == p->type && 
    1667         132 :                                 zend_hash_find(EG(function_table), p->save_func,
    1668         264 :                                                            strlen(p->save_func)+1, (void **)&orig) == SUCCESS) {
    1669             :                                 
    1670         132 :                                 zend_hash_update(EG(function_table), p->orig_func, strlen(p->orig_func)+1, orig, sizeof(zend_function), NULL);
    1671         132 :                                 zend_hash_del(EG(function_table), p->save_func, strlen(p->save_func)+1);
    1672             :                         }
    1673         144 :                         p++;
    1674             :                 }
    1675             :         }
    1676             : 
    1677             : #if HAVE_MBREGEX
    1678       20220 :         PHP_RSHUTDOWN(mb_regex) (INIT_FUNC_ARGS_PASSTHRU);
    1679             : #endif
    1680             : 
    1681       20220 :         return SUCCESS;
    1682             : }
    1683             : /* }}} */
    1684             : 
    1685             : /* {{{ PHP_MINFO_FUNCTION(mbstring) */
    1686         148 : PHP_MINFO_FUNCTION(mbstring)
    1687             : {
    1688         148 :         php_info_print_table_start();
    1689         148 :         php_info_print_table_row(2, "Multibyte Support", "enabled");
    1690         148 :         php_info_print_table_row(2, "Multibyte string engine", "libmbfl");
    1691         148 :         php_info_print_table_row(2, "HTTP input encoding translation", MBSTRG(encoding_translation) ? "enabled": "disabled");
    1692             :         {
    1693             :                 char tmp[256];
    1694         148 :                 snprintf(tmp, sizeof(tmp), "%d.%d.%d", MBFL_VERSION_MAJOR, MBFL_VERSION_MINOR, MBFL_VERSION_TEENY);
    1695         148 :                 php_info_print_table_row(2, "libmbfl version", tmp);
    1696             :         }       
    1697         148 :         php_info_print_table_end();
    1698             : 
    1699         148 :         php_info_print_table_start();
    1700         148 :         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         148 :         php_info_print_table_end();
    1702             : 
    1703             : #if HAVE_MBREGEX
    1704         148 :         PHP_MINFO(mb_regex)(ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU);
    1705             : #endif
    1706             : 
    1707         148 :         DISPLAY_INI_ENTRIES();
    1708         148 : }
    1709             : /* }}} */
    1710             : 
    1711             : /* {{{ proto string mb_language([string language])
    1712             :    Sets the current language or Returns the current language as a string */
    1713          30 : PHP_FUNCTION(mb_language)
    1714             : {
    1715          30 :         char *name = NULL;
    1716          30 :         int name_len = 0;
    1717             : 
    1718          30 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) {
    1719           0 :                 return;
    1720             :         }
    1721          30 :         if (name == NULL) {
    1722          15 :                 RETVAL_STRING((char *)mbfl_no_language2name(MBSTRG(language)), 1);
    1723             :         } else {
    1724          15 :                 if (FAILURE == zend_alter_ini_entry(
    1725             :                                 "mbstring.language", sizeof("mbstring.language"),
    1726             :                                 name, name_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME)) {
    1727           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown language \"%s\"", name);
    1728           0 :                         RETVAL_FALSE;
    1729             :                 } else {
    1730          15 :                         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         315 : PHP_FUNCTION(mb_internal_encoding)
    1739             : {
    1740         315 :         const char *name = NULL;
    1741             :         int name_len;
    1742             :         const mbfl_encoding *encoding;
    1743             : 
    1744         315 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &name, &name_len) == FAILURE) {
    1745           4 :                 RETURN_FALSE;
    1746             :         }
    1747         311 :         if (name == NULL) {
    1748         141 :                 name = MBSTRG(current_internal_encoding) ? MBSTRG(current_internal_encoding)->name: NULL;
    1749         141 :                 if (name != NULL) {
    1750         141 :                         RETURN_STRING(name, 1);
    1751             :                 } else {
    1752           0 :                         RETURN_FALSE;
    1753             :                 }
    1754             :         } else {
    1755         170 :                 encoding = mbfl_name2encoding(name);
    1756         170 :                 if (!encoding) {
    1757          21 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
    1758          21 :                         RETURN_FALSE;
    1759             :                 } else {
    1760         149 :                         MBSTRG(current_internal_encoding) = encoding;
    1761         149 :                         RETURN_TRUE;
    1762             :                 }
    1763             :         }
    1764             : }
    1765             : /* }}} */
    1766             : 
    1767             : /* {{{ proto mixed mb_http_input([string type])
    1768             :    Returns the input encoding */
    1769           2 : PHP_FUNCTION(mb_http_input)
    1770             : {
    1771           2 :         char *typ = NULL;
    1772             :         int typ_len;
    1773             :         int retname;
    1774             :         char *list, *temp;
    1775           2 :         const mbfl_encoding *result = NULL;
    1776             : 
    1777           2 :         retname = 1;
    1778           2 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &typ, &typ_len) == FAILURE) {
    1779           0 :                 RETURN_FALSE;
    1780             :         }
    1781           2 :         if (typ == NULL) {
    1782           1 :                 result = MBSTRG(http_input_identify);
    1783             :         } else {
    1784           1 :                 switch (*typ) {
    1785             :                 case 'G':
    1786             :                 case 'g':
    1787           0 :                         result = MBSTRG(http_input_identify_get);
    1788           0 :                         break;
    1789             :                 case 'P':
    1790             :                 case 'p':
    1791           0 :                         result = MBSTRG(http_input_identify_post);
    1792           0 :                         break;
    1793             :                 case 'C':
    1794             :                 case 'c':
    1795           0 :                         result = MBSTRG(http_input_identify_cookie);
    1796           0 :                         break;
    1797             :                 case 'S':
    1798             :                 case 's':
    1799           0 :                         result = MBSTRG(http_input_identify_string);
    1800           0 :                         break;
    1801             :                 case 'I':
    1802             :                 case 'i':
    1803             :                         {
    1804           0 :                                 const mbfl_encoding **entry = MBSTRG(http_input_list);
    1805           0 :                                 const size_t n = MBSTRG(http_input_list_size);
    1806             :                                 size_t i;
    1807           0 :                                 array_init(return_value);
    1808           0 :                                 for (i = 0; i < n; i++) {
    1809           0 :                                         add_next_index_string(return_value, (*entry)->name, 1);
    1810           0 :                                         entry++;
    1811             :                                 }
    1812           0 :                                 retname = 0;
    1813             :                         }
    1814           0 :                         break;
    1815             :                 case 'L':
    1816             :                 case 'l':
    1817             :                         {
    1818           1 :                                 const mbfl_encoding **entry = MBSTRG(http_input_list);
    1819           1 :                                 const size_t n = MBSTRG(http_input_list_size);
    1820             :                                 size_t i;
    1821           1 :                                 list = NULL;
    1822           2 :                                 for (i = 0; i < n; i++) {
    1823           1 :                                         if (list) {
    1824           0 :                                                 temp = list;
    1825           0 :                                                 spprintf(&list, 0, "%s,%s", temp, (*entry)->name);
    1826           0 :                                                 efree(temp);
    1827           0 :                                                 if (!list) { 
    1828           0 :                                                         break;
    1829             :                                                 }
    1830             :                                         } else {
    1831           1 :                                                 list = estrdup((*entry)->name);
    1832             :                                         }
    1833           1 :                                         entry++;
    1834             :                                 }
    1835             :                         }
    1836           1 :                         if (!list) {
    1837           0 :                                 RETURN_FALSE;
    1838             :                         }
    1839           1 :                         RETVAL_STRING(list, 0);
    1840           1 :                         retname = 0;
    1841           1 :                         break;
    1842             :                 default:
    1843           0 :                         result = MBSTRG(http_input_identify);
    1844             :                         break;
    1845             :                 }
    1846             :         }
    1847             : 
    1848           2 :         if (retname) {
    1849           1 :                 if (result) {
    1850           1 :                         RETVAL_STRING(result->name, 1);
    1851             :                 } else {
    1852           0 :                         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          32 : PHP_FUNCTION(mb_http_output)
    1861             : {
    1862          32 :         const char *name = NULL;
    1863             :         int name_len;
    1864             :         const mbfl_encoding *encoding;
    1865             : 
    1866          32 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", (char **)&name, &name_len) == FAILURE) {
    1867           2 :                 RETURN_FALSE;
    1868             :         }
    1869             : 
    1870          30 :         if (name == NULL) {
    1871           9 :                 name = MBSTRG(current_http_output_encoding) ? MBSTRG(current_http_output_encoding)->name: NULL;
    1872           9 :                 if (name != NULL) {
    1873           9 :                         RETURN_STRING(name, 1);
    1874             :                 } else {
    1875           0 :                         RETURN_FALSE;
    1876             :                 }
    1877             :         } else {
    1878          21 :                 encoding = mbfl_name2encoding(name);
    1879          21 :                 if (!encoding) {
    1880           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
    1881           1 :                         RETURN_FALSE;
    1882             :                 } else {
    1883          20 :                         MBSTRG(current_http_output_encoding) = encoding;
    1884          20 :                         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          12 : PHP_FUNCTION(mb_detect_order)
    1893             : {
    1894          12 :         zval **arg1 = NULL;
    1895             : 
    1896          12 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|Z", &arg1) == FAILURE) {
    1897           0 :                 return;
    1898             :         }
    1899             : 
    1900          12 :         if (!arg1) {
    1901             :                 size_t i;
    1902           5 :                 size_t n = MBSTRG(current_detect_order_list_size);
    1903           5 :                 const mbfl_encoding **entry = MBSTRG(current_detect_order_list);
    1904           5 :                 array_init(return_value);
    1905          26 :                 for (i = 0; i < n; i++) {
    1906          21 :                         add_next_index_string(return_value, (*entry)->name, 1);
    1907          21 :                         entry++;
    1908             :                 }
    1909             :         } else {
    1910           7 :                 const mbfl_encoding **list = NULL;
    1911           7 :                 size_t size = 0;
    1912           7 :                 switch (Z_TYPE_PP(arg1)) {
    1913             :                 case IS_ARRAY:
    1914           2 :                         if (FAILURE == php_mb_parse_encoding_array(*arg1, &list, &size, 0 TSRMLS_CC)) {
    1915           1 :                                 if (list) {
    1916           1 :                                         efree(list);
    1917             :                                 }
    1918           1 :                                 RETURN_FALSE;
    1919             :                         }
    1920           1 :                         break;
    1921             :                 default:
    1922           5 :                         convert_to_string_ex(arg1);
    1923           5 :                         if (FAILURE == php_mb_parse_encoding_list(Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1), &list, &size, 0 TSRMLS_CC)) {
    1924           0 :                                 if (list) {
    1925           0 :                                         efree(list);
    1926             :                                 }
    1927           0 :                                 RETURN_FALSE;
    1928             :                         }
    1929             :                         break;
    1930             :                 }
    1931             : 
    1932           6 :                 if (list == NULL) {
    1933           1 :                         RETURN_FALSE;
    1934             :                 }
    1935             : 
    1936           5 :                 if (MBSTRG(current_detect_order_list)) {
    1937           5 :                         efree(MBSTRG(current_detect_order_list));
    1938             :                 }
    1939           5 :                 MBSTRG(current_detect_order_list) = list;
    1940           5 :                 MBSTRG(current_detect_order_list_size) = size;
    1941           5 :                 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          53 : PHP_FUNCTION(mb_substitute_character)
    1949             : {
    1950          53 :         zval **arg1 = NULL;
    1951             : 
    1952          53 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|Z", &arg1) == FAILURE) {
    1953           1 :                 return;
    1954             :         }
    1955             : 
    1956          52 :         if (!arg1) {
    1957           8 :                 if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
    1958           2 :                         RETURN_STRING("none", 1);
    1959           6 :                 } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG) {
    1960           1 :                         RETURN_STRING("long", 1);
    1961           5 :                 } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY) {
    1962           1 :                         RETURN_STRING("entity", 1);
    1963             :                 } else {
    1964           4 :                         RETURN_LONG(MBSTRG(current_filter_illegal_substchar));
    1965             :                 }
    1966             :         } else {
    1967          44 :                 RETVAL_TRUE;
    1968             : 
    1969          44 :                 switch (Z_TYPE_PP(arg1)) {
    1970             :                 case IS_STRING:
    1971          13 :                         if (strncasecmp("none", Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1)) == 0) {
    1972           5 :                                 MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE;
    1973           8 :                         } else if (strncasecmp("long", Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1)) == 0) {
    1974           1 :                                 MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG;
    1975           7 :                         } else if (strncasecmp("entity", Z_STRVAL_PP(arg1), Z_STRLEN_PP(arg1)) == 0) {
    1976           1 :                                 MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY;
    1977             :                         } else {
    1978          32 :                                 convert_to_long_ex(arg1);
    1979             : 
    1980           6 :                                 if (Z_LVAL_PP(arg1) < 0xffff && Z_LVAL_PP(arg1) > 0x0) {
    1981           0 :                                         MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
    1982           0 :                                         MBSTRG(current_filter_illegal_substchar) = Z_LVAL_PP(arg1);
    1983             :                                 } else {
    1984           6 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown character.");
    1985           6 :                                         RETURN_FALSE;
    1986             :                                 }
    1987             :                         }
    1988           7 :                         break;
    1989             :                 default:
    1990         122 :                         convert_to_long_ex(arg1);
    1991          49 :                         if (Z_LVAL_PP(arg1) < 0xffff && Z_LVAL_PP(arg1) > 0x0) {
    1992          18 :                                 MBSTRG(current_filter_illegal_mode) = MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR;
    1993          18 :                                 MBSTRG(current_filter_illegal_substchar) = Z_LVAL_PP(arg1);
    1994             :                         } else {
    1995          13 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown character.");
    1996          13 :                                 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          10 : PHP_FUNCTION(mb_preferred_mime_name)
    2007             : {
    2008             :         enum mbfl_no_encoding no_encoding;
    2009          10 :         char *name = NULL;
    2010             :         int name_len;
    2011             : 
    2012          10 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
    2013           0 :                 return;
    2014             :         } else {
    2015          10 :                 no_encoding = mbfl_name2no_encoding(name);
    2016          10 :                 if (no_encoding == mbfl_no_encoding_invalid) {
    2017           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
    2018           1 :                         RETVAL_FALSE;
    2019             :                 } else {
    2020           9 :                         const char *preferred_name = mbfl_no2preferred_mime_name(no_encoding);
    2021           9 :                         if (preferred_name == NULL || *preferred_name == '\0') {
    2022           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No MIME preferred name corresponding to \"%s\"", name);
    2023           0 :                                 RETVAL_FALSE;
    2024             :                         } else {
    2025           9 :                                 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          17 : PHP_FUNCTION(mb_parse_str)
    2038             : {
    2039          17 :         zval *track_vars_array = NULL;
    2040          17 :         char *encstr = NULL;
    2041             :         int encstr_len;
    2042             :         php_mb_encoding_handler_info_t info;
    2043             :         const mbfl_encoding *detected;
    2044             : 
    2045          17 :         track_vars_array = NULL;
    2046          17 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &encstr, &encstr_len, &track_vars_array) == FAILURE) {
    2047           0 :                 return;
    2048             :         }
    2049             : 
    2050          17 :         if (track_vars_array != NULL) {
    2051             :                 /* Clear out the array */
    2052           9 :                 zval_dtor(track_vars_array);
    2053           9 :                 array_init(track_vars_array);
    2054             :         }
    2055             : 
    2056          17 :         encstr = estrndup(encstr, encstr_len);
    2057             : 
    2058          17 :         info.data_type              = PARSE_STRING;
    2059          17 :         info.separator              = PG(arg_separator).input; 
    2060          17 :         info.report_errors          = 1;
    2061          17 :         info.to_encoding            = MBSTRG(current_internal_encoding);
    2062          17 :         info.to_language            = MBSTRG(language);
    2063          17 :         info.from_encodings         = MBSTRG(http_input_list);
    2064          17 :         info.num_from_encodings     = MBSTRG(http_input_list_size); 
    2065          17 :         info.from_language          = MBSTRG(language);
    2066             : 
    2067          17 :         if (track_vars_array != NULL) {
    2068           9 :                 detected = _php_mb_encoding_handler_ex(&info, track_vars_array, encstr TSRMLS_CC);
    2069             :         } else {
    2070             :                 zval tmp;
    2071           8 :                 if (!EG(active_symbol_table)) {
    2072           6 :                         zend_rebuild_symbol_table(TSRMLS_C);
    2073             :                 }
    2074           8 :                 Z_ARRVAL(tmp) = EG(active_symbol_table);                
    2075           8 :                 detected = _php_mb_encoding_handler_ex(&info, &tmp, encstr TSRMLS_CC);          
    2076             :         }
    2077             : 
    2078          17 :         MBSTRG(http_input_identify) = detected;
    2079             : 
    2080          17 :         RETVAL_BOOL(detected);
    2081             : 
    2082          17 :         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          19 : 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;
    2096             :         const mbfl_encoding *encoding;
    2097             :         int last_feed, len;
    2098          19 :         unsigned char send_text_mimetype = 0;
    2099          19 :         char *s, *mimetype = NULL;
    2100             : 
    2101          19 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &arg_string, &arg_string_len, &arg_status) == FAILURE) {
    2102           0 :                 return;
    2103             :         }
    2104             : 
    2105          19 :         encoding = MBSTRG(current_http_output_encoding);
    2106             : 
    2107             :         /* start phase only */
    2108          19 :         if ((arg_status & PHP_OUTPUT_HANDLER_START) != 0) {
    2109             :                 /* delete the converter just in case. */
    2110          19 :                 if (MBSTRG(outconv)) {
    2111           0 :                         MBSTRG(illegalchars) += mbfl_buffer_illegalchars(MBSTRG(outconv));
    2112           0 :                         mbfl_buffer_converter_delete(MBSTRG(outconv));
    2113           0 :                         MBSTRG(outconv) = NULL;
    2114             :                 }
    2115          19 :                 if (encoding == &mbfl_encoding_pass) {
    2116           0 :                         RETURN_STRINGL(arg_string, arg_string_len, 1);
    2117             :                 }
    2118             : 
    2119             :                 /* analyze mime type */
    2120          39 :                 if (SG(sapi_headers).mimetype &&
    2121             :                         _php_mb_match_regex(
    2122             :                                 MBSTRG(http_output_conv_mimetypes),
    2123          12 :                                 SG(sapi_headers).mimetype,
    2124          24 :                                 strlen(SG(sapi_headers).mimetype))) {
    2125           8 :                         if ((s = strchr(SG(sapi_headers).mimetype,';')) == NULL){
    2126           8 :                                 mimetype = estrdup(SG(sapi_headers).mimetype);
    2127             :                         } else {
    2128           0 :                                 mimetype = estrndup(SG(sapi_headers).mimetype,s-SG(sapi_headers).mimetype);
    2129             :                         }
    2130           8 :                         send_text_mimetype = 1;
    2131          11 :                 } else if (SG(sapi_headers).send_default_content_type) {
    2132           7 :                         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          19 :                 if (SG(sapi_headers).send_default_content_type || send_text_mimetype) {
    2137          15 :                         charset = encoding->mime_name;
    2138          15 :                         if (charset) {
    2139          15 :                                 len = spprintf( &p, 0, "Content-Type: %s; charset=%s",  mimetype, charset ); 
    2140          15 :                                 if (sapi_add_header(p, len, 0) != FAILURE) {
    2141          15 :                                         SG(sapi_headers).send_default_content_type = 0;
    2142             :                                 }
    2143             :                         }
    2144             :                         /* activate the converter */
    2145          15 :                         MBSTRG(outconv) = mbfl_buffer_converter_new2(MBSTRG(current_internal_encoding), encoding, 0);
    2146          15 :                         if (send_text_mimetype){
    2147           8 :                                 efree(mimetype);
    2148             :                         }
    2149             :                 }
    2150             :         }
    2151             : 
    2152             :         /* just return if the converter is not activated. */
    2153          19 :         if (MBSTRG(outconv) == NULL) {
    2154           4 :                 RETURN_STRINGL(arg_string, arg_string_len, 1);
    2155             :         }
    2156             : 
    2157             :         /* flag */
    2158          15 :         last_feed = ((arg_status & PHP_OUTPUT_HANDLER_END) != 0);
    2159             :         /* mode */
    2160          15 :         mbfl_buffer_converter_illegal_mode(MBSTRG(outconv), MBSTRG(current_filter_illegal_mode));
    2161          15 :         mbfl_buffer_converter_illegal_substchar(MBSTRG(outconv), MBSTRG(current_filter_illegal_substchar));
    2162             :  
    2163             :         /* feed the string */
    2164          15 :         mbfl_string_init(&string);
    2165          15 :         string.no_language = MBSTRG(language);
    2166          15 :         string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2167          15 :         string.val = (unsigned char *)arg_string;
    2168          15 :         string.len = arg_string_len;
    2169          15 :         mbfl_buffer_converter_feed(MBSTRG(outconv), &string);
    2170          15 :         if (last_feed) {
    2171          15 :                 mbfl_buffer_converter_flush(MBSTRG(outconv));
    2172             :         } 
    2173             :         /* get the converter output, and return it */
    2174          15 :         mbfl_buffer_converter_result(MBSTRG(outconv), &result);
    2175          15 :         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          15 :         if (last_feed) {
    2179          15 :                 MBSTRG(illegalchars) += mbfl_buffer_illegalchars(MBSTRG(outconv));
    2180          15 :                 mbfl_buffer_converter_delete(MBSTRG(outconv));
    2181          15 :                 MBSTRG(outconv) = NULL;
    2182             :         }
    2183             : }
    2184             : /* }}} */
    2185             : 
    2186             : /* {{{ proto int mb_strlen(string str [, string encoding])
    2187             :    Get character numbers of a string */
    2188         229 : PHP_FUNCTION(mb_strlen)
    2189             : {
    2190             :         int n;
    2191             :         mbfl_string string;
    2192         229 :         char *enc_name = NULL;
    2193             :         int enc_name_len;
    2194             : 
    2195         229 :         mbfl_string_init(&string);
    2196             : 
    2197         229 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", (char **)&string.val, &string.len, &enc_name, &enc_name_len) == FAILURE) {
    2198           4 :                 RETURN_FALSE;
    2199             :         }
    2200             : 
    2201         225 :         string.no_language = MBSTRG(language);
    2202         225 :         if (enc_name == NULL) {
    2203           5 :                 string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2204             :         } else {
    2205         220 :                 string.no_encoding = mbfl_name2no_encoding(enc_name);
    2206         220 :                 if (string.no_encoding == mbfl_no_encoding_invalid) {
    2207          21 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
    2208          21 :                         RETURN_FALSE;
    2209             :                 }
    2210             :         }
    2211             : 
    2212         204 :         n = mbfl_strlen(&string);
    2213         204 :         if (n >= 0) {
    2214         204 :                 RETVAL_LONG(n);
    2215             :         } else {
    2216           0 :                 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         181 : PHP_FUNCTION(mb_strpos)
    2224             : {
    2225         181 :         int n, reverse = 0;
    2226             :         long offset;
    2227             :         mbfl_string haystack, needle;
    2228         181 :         char *enc_name = NULL;
    2229             :         int enc_name_len;
    2230             : 
    2231         181 :         mbfl_string_init(&haystack);
    2232         181 :         mbfl_string_init(&needle);
    2233         181 :         haystack.no_language = MBSTRG(language);
    2234         181 :         haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2235         181 :         needle.no_language = MBSTRG(language);
    2236         181 :         needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2237         181 :         offset = 0;
    2238             : 
    2239         181 :         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          16 :                 RETURN_FALSE;
    2241             :         }
    2242             : 
    2243         165 :         if (enc_name != NULL) {
    2244         124 :                 haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
    2245         124 :                 if (haystack.no_encoding == mbfl_no_encoding_invalid) {
    2246          20 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
    2247          20 :                         RETURN_FALSE;
    2248             :                 }
    2249             :         }
    2250             : 
    2251         145 :         if (offset < 0 || offset > mbfl_strlen(&haystack)) {
    2252          32 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset not contained in string");
    2253          32 :                 RETURN_FALSE;
    2254             :         }
    2255         113 :         if (needle.len == 0) {
    2256           8 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
    2257           8 :                 RETURN_FALSE;
    2258             :         }
    2259             : 
    2260         105 :         n = mbfl_strpos(&haystack, &needle, offset, reverse);
    2261         105 :         if (n >= 0) {
    2262          52 :                 RETVAL_LONG(n);
    2263             :         } else {
    2264          53 :                 switch (-n) {
    2265             :                 case 1:
    2266          53 :                         break;
    2267             :                 case 2:
    2268           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Needle has not positive length");
    2269           0 :                         break;
    2270             :                 case 4:
    2271           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding or conversion error");
    2272           0 :                         break;
    2273             :                 case 8:
    2274           0 :                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Argument is empty");
    2275           0 :                         break;
    2276             :                 default:
    2277           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error in mb_strpos");
    2278             :                         break;
    2279             :                 }
    2280          53 :                 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         121 : PHP_FUNCTION(mb_strrpos)
    2288             : {
    2289             :         int n;
    2290             :         mbfl_string haystack, needle;
    2291         121 :         char *enc_name = NULL;
    2292             :         int enc_name_len;
    2293         121 :         zval **zoffset = NULL;
    2294         121 :         long offset = 0, str_flg;
    2295         121 :         char *enc_name2 = NULL;
    2296             :         int enc_name_len2;
    2297             : 
    2298         121 :         mbfl_string_init(&haystack);
    2299         121 :         mbfl_string_init(&needle);
    2300         121 :         haystack.no_language = MBSTRG(language);
    2301         121 :         haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2302         121 :         needle.no_language = MBSTRG(language);
    2303         121 :         needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2304             : 
    2305         121 :         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           5 :                 RETURN_FALSE;
    2307             :         }
    2308             : 
    2309         116 :         if (zoffset) {
    2310         113 :                 if (Z_TYPE_PP(zoffset) == IS_STRING) {
    2311           6 :                         enc_name2     = Z_STRVAL_PP(zoffset);
    2312           6 :                         enc_name_len2 = Z_STRLEN_PP(zoffset);
    2313           6 :                         str_flg       = 1;
    2314             : 
    2315           6 :                         if (enc_name2 != NULL) {
    2316           6 :                                 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           0 :                                         break;
    2331             :                                 default :
    2332           6 :                                         str_flg = 0;
    2333             :                                         break;
    2334             :                                 }
    2335             :                         }
    2336             : 
    2337           6 :                         if (str_flg) {
    2338           0 :                                 convert_to_long_ex(zoffset);
    2339           0 :                                 offset   = Z_LVAL_PP(zoffset);
    2340             :                         } else {
    2341           6 :                                 enc_name     = enc_name2;
    2342           6 :                                 enc_name_len = enc_name_len2;
    2343             :                         }
    2344             :                 } else {
    2345         176 :                         convert_to_long_ex(zoffset);
    2346         107 :                         offset = Z_LVAL_PP(zoffset);
    2347             :                 }
    2348             :         }
    2349             : 
    2350         116 :         if (enc_name != NULL) {
    2351         100 :                 haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
    2352         100 :                 if (haystack.no_encoding == mbfl_no_encoding_invalid) {
    2353          20 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
    2354          20 :                         RETURN_FALSE;
    2355             :                 }
    2356             :         }
    2357             : 
    2358          96 :         if (haystack.len <= 0) {
    2359           8 :                 RETURN_FALSE;
    2360             :         }
    2361          88 :         if (needle.len <= 0) {
    2362           8 :                 RETURN_FALSE;
    2363             :         }
    2364             : 
    2365             :         {
    2366          80 :                 int haystack_char_len = mbfl_strlen(&haystack);
    2367          93 :                 if ((offset > 0 && offset > haystack_char_len) ||
    2368          13 :                         (offset < 0 && -offset > haystack_char_len)) {
    2369           8 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset is greater than the length of haystack string");
    2370           8 :                         RETURN_FALSE;
    2371             :                 }
    2372             :         }
    2373             : 
    2374          72 :         n = mbfl_strpos(&haystack, &needle, offset, 1);
    2375          72 :         if (n >= 0) {
    2376          42 :                 RETVAL_LONG(n);
    2377             :         } else {
    2378          30 :                 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         259 : PHP_FUNCTION(mb_stripos)
    2386             : {
    2387             :         int n;
    2388             :         long offset;
    2389             :         mbfl_string haystack, needle;
    2390         259 :         const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
    2391             :         int from_encoding_len;
    2392         259 :         n = -1;
    2393         259 :         offset = 0;
    2394             : 
    2395         259 :         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          16 :                 RETURN_FALSE;
    2397             :         }
    2398         243 :         if (needle.len == 0) {
    2399           8 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
    2400           8 :                 RETURN_FALSE;
    2401             :         }
    2402         235 :         n = php_mb_stripos(0, (char *)haystack.val, haystack.len, (char *)needle.val, needle.len, offset, from_encoding TSRMLS_CC);
    2403             : 
    2404         235 :         if (n >= 0) {
    2405         116 :                 RETVAL_LONG(n);
    2406             :         } else {
    2407         119 :                 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         223 : PHP_FUNCTION(mb_strripos)
    2415             : {
    2416             :         int n;
    2417             :         long offset;
    2418             :         mbfl_string haystack, needle;
    2419         223 :         const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
    2420             :         int from_encoding_len;
    2421         223 :         n = -1;
    2422         223 :         offset = 0;
    2423             : 
    2424         223 :         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          12 :                 RETURN_FALSE;
    2426             :         }
    2427             : 
    2428         211 :         n = php_mb_stripos(1, (char *)haystack.val, haystack.len, (char *)needle.val, needle.len, offset, from_encoding TSRMLS_CC);
    2429             : 
    2430         211 :         if (n >= 0) {
    2431          83 :                 RETVAL_LONG(n);
    2432             :         } else {
    2433         128 :                 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         138 : PHP_FUNCTION(mb_strstr)
    2441             : {
    2442             :         int n, len, mblen;
    2443         138 :         mbfl_string haystack, needle, result, *ret = NULL;
    2444         138 :         char *enc_name = NULL;
    2445             :         int enc_name_len;
    2446         138 :         zend_bool part = 0;
    2447             : 
    2448         138 :         mbfl_string_init(&haystack);
    2449         138 :         mbfl_string_init(&needle);
    2450         138 :         haystack.no_language = MBSTRG(language);
    2451         138 :         haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2452         138 :         needle.no_language = MBSTRG(language);
    2453         138 :         needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2454             : 
    2455         138 :         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          27 :                 RETURN_FALSE;
    2457             :         }
    2458             : 
    2459         111 :         if (enc_name != NULL) {
    2460          89 :                 haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
    2461          89 :                 if (haystack.no_encoding == mbfl_no_encoding_invalid) {
    2462          21 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
    2463          21 :                         RETURN_FALSE;
    2464             :                 }
    2465             :         }
    2466             : 
    2467          90 :         if (needle.len <= 0) {
    2468           8 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
    2469           8 :                 RETURN_FALSE;
    2470             :         }
    2471          82 :         n = mbfl_strpos(&haystack, &needle, 0, 0);
    2472          82 :         if (n >= 0) {
    2473          44 :                 mblen = mbfl_strlen(&haystack);
    2474          44 :                 if (part) {
    2475          21 :                         ret = mbfl_substr(&haystack, &result, 0, n);
    2476          21 :                         if (ret != NULL) {
    2477          21 :                                 RETVAL_STRINGL((char *)ret->val, ret->len, 0);
    2478             :                         } else {
    2479           0 :                                 RETVAL_FALSE;
    2480             :                         }
    2481             :                 } else {
    2482          23 :                         len = (mblen - n);
    2483          23 :                         ret = mbfl_substr(&haystack, &result, n, len);
    2484          23 :                         if (ret != NULL) {
    2485          23 :                                 RETVAL_STRINGL((char *)ret->val, ret->len, 0);
    2486             :                         } else {
    2487           0 :                                 RETVAL_FALSE;
    2488             :                         }
    2489             :                 }
    2490             :         } else {
    2491          38 :                 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         130 : PHP_FUNCTION(mb_strrchr)
    2499             : {
    2500             :         int n, len, mblen;
    2501         130 :         mbfl_string haystack, needle, result, *ret = NULL;
    2502         130 :         char *enc_name = NULL;
    2503             :         int enc_name_len;
    2504         130 :         zend_bool part = 0;
    2505             : 
    2506         130 :         mbfl_string_init(&haystack);
    2507         130 :         mbfl_string_init(&needle);
    2508         130 :         haystack.no_language = MBSTRG(language);
    2509         130 :         haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2510         130 :         needle.no_language = MBSTRG(language);
    2511         130 :         needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2512             : 
    2513         130 :         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          27 :                 RETURN_FALSE;
    2515             :         }
    2516             : 
    2517         103 :         if (enc_name != NULL) {
    2518          87 :                 haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
    2519          87 :                 if (haystack.no_encoding == mbfl_no_encoding_invalid) {
    2520          21 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
    2521          21 :                         RETURN_FALSE;
    2522             :                 }
    2523             :         }
    2524             : 
    2525          82 :         if (haystack.len <= 0) {
    2526           8 :                 RETURN_FALSE;
    2527             :         }
    2528          74 :         if (needle.len <= 0) {
    2529           8 :                 RETURN_FALSE;
    2530             :         }
    2531          66 :         n = mbfl_strpos(&haystack, &needle, 0, 1);
    2532          66 :         if (n >= 0) {
    2533          36 :                 mblen = mbfl_strlen(&haystack);
    2534          36 :                 if (part) {
    2535          18 :                         ret = mbfl_substr(&haystack, &result, 0, n);
    2536          18 :                         if (ret != NULL) {
    2537          18 :                                 RETVAL_STRINGL((char *)ret->val, ret->len, 0);
    2538             :                         } else {
    2539           0 :                                 RETVAL_FALSE;
    2540             :                         }
    2541             :                 } else {
    2542          18 :                         len = (mblen - n);
    2543          18 :                         ret = mbfl_substr(&haystack, &result, n, len);
    2544          18 :                         if (ret != NULL) {
    2545          18 :                                 RETVAL_STRINGL((char *)ret->val, ret->len, 0);
    2546             :                         } else {
    2547           0 :                                 RETVAL_FALSE;
    2548             :                         }
    2549             :                 }
    2550             :         } else {
    2551          30 :                 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         132 : PHP_FUNCTION(mb_stristr)
    2559             : {
    2560         132 :         zend_bool part = 0;
    2561             :         unsigned int from_encoding_len, len, mblen;
    2562             :         int n;
    2563         132 :         mbfl_string haystack, needle, result, *ret = NULL;
    2564         132 :         const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
    2565         132 :         mbfl_string_init(&haystack);
    2566         132 :         mbfl_string_init(&needle);
    2567         132 :         haystack.no_language = MBSTRG(language);
    2568         132 :         haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2569         132 :         needle.no_language = MBSTRG(language);
    2570         132 :         needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2571             : 
    2572             : 
    2573         132 :         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          27 :                 RETURN_FALSE;
    2575             :         }
    2576             : 
    2577         105 :         if (!needle.len) {
    2578           8 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter");
    2579           8 :                 RETURN_FALSE;
    2580             :         }
    2581             : 
    2582          97 :         haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(from_encoding);
    2583          97 :         if (haystack.no_encoding == mbfl_no_encoding_invalid) {
    2584          21 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", from_encoding);
    2585          21 :                 RETURN_FALSE;
    2586             :         }
    2587             : 
    2588          76 :         n = php_mb_stripos(0, (char *)haystack.val, haystack.len, (char *)needle.val, needle.len, 0, from_encoding TSRMLS_CC);
    2589             : 
    2590          76 :         if (n <0) {
    2591          34 :                 RETURN_FALSE;
    2592             :         }
    2593             : 
    2594          42 :         mblen = mbfl_strlen(&haystack);
    2595             : 
    2596          42 :         if (part) {
    2597          22 :                 ret = mbfl_substr(&haystack, &result, 0, n);
    2598          22 :                 if (ret != NULL) {
    2599          22 :                         RETVAL_STRINGL((char *)ret->val, ret->len, 0);
    2600             :                 } else {
    2601           0 :                         RETVAL_FALSE;
    2602             :                 }
    2603             :         } else {
    2604          20 :                 len = (mblen - n);
    2605          20 :                 ret = mbfl_substr(&haystack, &result, n, len);
    2606          20 :                 if (ret != NULL) {
    2607          20 :                         RETVAL_STRINGL((char *)ret->val, ret->len, 0);
    2608             :                 } else {
    2609           0 :                         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         132 : PHP_FUNCTION(mb_strrichr)
    2618             : {
    2619         132 :         zend_bool part = 0;
    2620             :         int n, from_encoding_len, len, mblen;
    2621         132 :         mbfl_string haystack, needle, result, *ret = NULL;
    2622         132 :         const char *from_encoding = MBSTRG(current_internal_encoding)->name;
    2623         132 :         mbfl_string_init(&haystack);
    2624         132 :         mbfl_string_init(&needle);
    2625         132 :         haystack.no_language = MBSTRG(language);
    2626         132 :         haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2627         132 :         needle.no_language = MBSTRG(language);
    2628         132 :         needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2629             : 
    2630             : 
    2631         132 :         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          27 :                 RETURN_FALSE;
    2633             :         }
    2634             : 
    2635         105 :         haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(from_encoding);
    2636         105 :         if (haystack.no_encoding == mbfl_no_encoding_invalid) {
    2637          21 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", from_encoding);
    2638          21 :                 RETURN_FALSE;
    2639             :         }
    2640             : 
    2641          84 :         n = php_mb_stripos(1, (char *)haystack.val, haystack.len, (char *)needle.val, needle.len, 0, from_encoding TSRMLS_CC);
    2642             : 
    2643          84 :         if (n <0) {
    2644          42 :                 RETURN_FALSE;
    2645             :         }
    2646             : 
    2647          42 :         mblen = mbfl_strlen(&haystack);
    2648             : 
    2649          42 :         if (part) {
    2650          22 :                 ret = mbfl_substr(&haystack, &result, 0, n);
    2651          22 :                 if (ret != NULL) {
    2652          22 :                         RETVAL_STRINGL((char *)ret->val, ret->len, 0);
    2653             :                 } else {
    2654           0 :                         RETVAL_FALSE;
    2655             :                 }
    2656             :         } else {
    2657          20 :                 len = (mblen - n);
    2658          20 :                 ret = mbfl_substr(&haystack, &result, n, len);
    2659          20 :                 if (ret != NULL) {
    2660          20 :                         RETVAL_STRINGL((char *)ret->val, ret->len, 0);
    2661             :                 } else {
    2662           0 :                         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         100 : PHP_FUNCTION(mb_substr_count)
    2671             : {
    2672             :         int n;
    2673             :         mbfl_string haystack, needle;
    2674         100 :         char *enc_name = NULL;
    2675             :         int enc_name_len;
    2676             : 
    2677         100 :         mbfl_string_init(&haystack);
    2678         100 :         mbfl_string_init(&needle);
    2679         100 :         haystack.no_language = MBSTRG(language);
    2680         100 :         haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2681         100 :         needle.no_language = MBSTRG(language);
    2682         100 :         needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2683             : 
    2684         100 :         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           5 :                 return;
    2686             :         }
    2687             : 
    2688          95 :         if (enc_name != NULL) {
    2689          27 :                 haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(enc_name);
    2690          27 :                 if (haystack.no_encoding == mbfl_no_encoding_invalid) {
    2691          20 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
    2692          20 :                         RETURN_FALSE;
    2693             :                 }
    2694             :         }
    2695             : 
    2696          75 :         if (needle.len <= 0) {
    2697          10 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty substring");
    2698          10 :                 RETURN_FALSE;
    2699             :         }
    2700             : 
    2701          65 :         n = mbfl_substr_count(&haystack, &needle);
    2702          65 :         if (n >= 0) {
    2703          65 :                 RETVAL_LONG(n);
    2704             :         } else {
    2705           0 :                 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         300 : PHP_FUNCTION(mb_substr)
    2713             : {
    2714         300 :         size_t argc = ZEND_NUM_ARGS();
    2715             :         char *str, *encoding;
    2716             :         long from, len;
    2717             :         int mblen, str_len, encoding_len;
    2718         300 :         zval **z_len = NULL;
    2719             :         mbfl_string string, result, *ret;
    2720             : 
    2721         300 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|Zs", &str, &str_len, &from, &z_len, &encoding, &encoding_len) == FAILURE) {
    2722           4 :                 return;
    2723             :         }
    2724             : 
    2725         296 :         mbfl_string_init(&string);
    2726         296 :         string.no_language = MBSTRG(language);
    2727         296 :         string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2728             : 
    2729         296 :         if (argc == 4) {
    2730         219 :                 string.no_encoding = mbfl_name2no_encoding(encoding);
    2731         219 :                 if (string.no_encoding == mbfl_no_encoding_invalid) {
    2732          20 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encoding);
    2733          20 :                         RETURN_FALSE;
    2734             :                 }
    2735             :         }
    2736             : 
    2737         276 :         string.val = (unsigned char *)str;
    2738         276 :         string.len = str_len;
    2739             : 
    2740         278 :         if (argc < 3 || Z_TYPE_PP(z_len) == IS_NULL) {
    2741           2 :                 len = str_len;
    2742             :         } else {
    2743         274 :                 convert_to_long_ex(z_len);
    2744         274 :                 len = Z_LVAL_PP(z_len);
    2745             :         }
    2746             : 
    2747             :         /* measures length */
    2748         276 :         mblen = 0;
    2749         276 :         if (from < 0 || len < 0) {
    2750          49 :                 mblen = mbfl_strlen(&string);
    2751             :         }
    2752             : 
    2753             :         /* if "from" position is negative, count start position from the end
    2754             :          * of the string
    2755             :          */
    2756         276 :         if (from < 0) {
    2757          25 :                 from = mblen + from;
    2758          25 :                 if (from < 0) {
    2759          17 :                         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         276 :         if (len < 0) {
    2767          24 :                 len = (mblen - from) + len;
    2768          24 :                 if (len < 0) {
    2769          16 :                         len = 0;
    2770             :                 }
    2771             :         }
    2772             : 
    2773         276 :         if (((MBSTRG(func_overload) & MB_OVERLOAD_STRING) == MB_OVERLOAD_STRING)
    2774           0 :                 && (from >= mbfl_strlen(&string))) {
    2775           0 :                 RETURN_FALSE;
    2776             :         }
    2777             : 
    2778         276 :         ret = mbfl_substr(&string, &result, from, len);
    2779         276 :         if (NULL == ret) {
    2780           0 :                 RETURN_FALSE;
    2781             :         }
    2782             : 
    2783         276 :         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          18 : PHP_FUNCTION(mb_strcut)
    2790             : {
    2791          18 :         size_t argc = ZEND_NUM_ARGS();
    2792             :         char *encoding;
    2793             :         long from, len;
    2794             :         int encoding_len;
    2795          18 :         zval **z_len = NULL;
    2796             :         mbfl_string string, result, *ret;
    2797             : 
    2798          18 :         mbfl_string_init(&string);
    2799          18 :         string.no_language = MBSTRG(language);
    2800          18 :         string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2801             : 
    2802          18 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|Zs", (char **)&string.val, (int **)&string.len, &from, &z_len, &encoding, &encoding_len) == FAILURE) {
    2803           0 :                 return;
    2804             :         }
    2805             : 
    2806          18 :         if (argc == 4) {
    2807          11 :                 string.no_encoding = mbfl_name2no_encoding(encoding);
    2808          11 :                 if (string.no_encoding == mbfl_no_encoding_invalid) {
    2809           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encoding);
    2810           0 :                         RETURN_FALSE;
    2811             :                 }
    2812             :         }
    2813             : 
    2814          19 :         if (argc < 3 || Z_TYPE_PP(z_len) == IS_NULL) {
    2815           1 :                 len = string.len;
    2816             :         } else {
    2817          17 :                 convert_to_long_ex(z_len);
    2818          17 :                 len = Z_LVAL_PP(z_len);
    2819             :         }
    2820             : 
    2821             :         /* if "from" position is negative, count start position from the end
    2822             :          * of the string
    2823             :          */
    2824          18 :         if (from < 0) {
    2825           1 :                 from = string.len + from;
    2826           1 :                 if (from < 0) {
    2827           1 :                         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          18 :         if (len < 0) {
    2835           0 :                 len = (string.len - from) + len;
    2836           0 :                 if (len < 0) {
    2837           0 :                         len = 0;
    2838             :                 }
    2839             :         }
    2840             : 
    2841          18 :         if ((unsigned int)from > string.len) {
    2842           2 :                 RETURN_FALSE;
    2843             :         }
    2844             : 
    2845          16 :         ret = mbfl_strcut(&string, &result, from, len);
    2846          16 :         if (ret == NULL) {
    2847           0 :                 RETURN_FALSE;
    2848             :         }
    2849             : 
    2850          16 :         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        8257 : PHP_FUNCTION(mb_strwidth)
    2857             : {
    2858             :         int n;
    2859             :         mbfl_string string;
    2860        8257 :         char *enc_name = NULL;
    2861             :         int enc_name_len;
    2862             : 
    2863        8257 :         mbfl_string_init(&string);
    2864             : 
    2865        8257 :         string.no_language = MBSTRG(language);
    2866        8257 :         string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2867             : 
    2868        8257 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", (char **)&string.val, &string.len, &enc_name, &enc_name_len) == FAILURE) {
    2869           0 :                 return;
    2870             :         }
    2871             : 
    2872        8257 :         if (enc_name != NULL) {
    2873        8257 :                 string.no_encoding = mbfl_name2no_encoding(enc_name);
    2874        8257 :                 if (string.no_encoding == mbfl_no_encoding_invalid) {
    2875           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", enc_name);
    2876           0 :                         RETURN_FALSE;
    2877             :                 }
    2878             :         }
    2879             : 
    2880        8257 :         n = mbfl_strwidth(&string);
    2881        8257 :         if (n >= 0) {
    2882        8257 :                 RETVAL_LONG(n);
    2883             :         } else {
    2884           0 :                 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           9 : 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           9 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll|ss", &str, &str_len, &from, &width, &trimmarker, &trimmarker_len, &encoding, &encoding_len) == FAILURE) {
    2899           0 :                 return;
    2900             :         }
    2901             : 
    2902           9 :         mbfl_string_init(&string);
    2903           9 :         mbfl_string_init(&marker);
    2904           9 :         string.no_language = MBSTRG(language);
    2905           9 :         string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2906           9 :         marker.no_language = MBSTRG(language);
    2907           9 :         marker.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    2908           9 :         marker.val = NULL;
    2909           9 :         marker.len = 0;
    2910             : 
    2911           9 :         if (ZEND_NUM_ARGS() == 5) {
    2912           9 :                 string.no_encoding = marker.no_encoding = mbfl_name2no_encoding(encoding);
    2913           9 :                 if (string.no_encoding == mbfl_no_encoding_invalid) {
    2914           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encoding);
    2915           0 :                         RETURN_FALSE;
    2916             :                 }
    2917             :         }
    2918             : 
    2919           9 :         string.val = (unsigned char *)str;
    2920           9 :         string.len = str_len;
    2921             : 
    2922           9 :         if (from < 0 || from > str_len) {
    2923           3 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Start position is out of range");
    2924           3 :                 RETURN_FALSE;
    2925             :         }
    2926             : 
    2927           6 :         if (width < 0) {
    2928           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Width is negative value");
    2929           0 :                 RETURN_FALSE;
    2930             :         }
    2931             : 
    2932           6 :         if (ZEND_NUM_ARGS() >= 4) {
    2933           6 :                 marker.val = (unsigned char *)trimmarker;
    2934           6 :                 marker.len = trimmarker_len;
    2935             :         }
    2936             : 
    2937           6 :         ret = mbfl_strimwidth(&string, &marker, &result, from, width);
    2938             : 
    2939           6 :         if (ret == NULL) {
    2940           0 :                 RETURN_FALSE;
    2941             :         }
    2942             : 
    2943           6 :         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       15067 : 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;
    2951             :         const mbfl_encoding *from_encoding, *to_encoding;
    2952             :         mbfl_buffer_converter *convd;
    2953             :         size_t size;
    2954             :         const mbfl_encoding **list;
    2955       15067 :         char *output=NULL;
    2956             : 
    2957       15067 :         if (output_len) {
    2958       15067 :                 *output_len = 0;
    2959             :         }
    2960       15067 :         if (!input) {
    2961           0 :                 return NULL;
    2962             :         }
    2963             :         /* new encoding */
    2964       30113 :         if (_to_encoding && strlen(_to_encoding)) {
    2965       15059 :                 to_encoding = mbfl_name2encoding(_to_encoding);
    2966       15059 :                 if (!to_encoding) {
    2967          13 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", _to_encoding);
    2968          13 :                         return NULL;
    2969             :                 }
    2970             :         } else {
    2971           8 :                 to_encoding = MBSTRG(current_internal_encoding);
    2972             :         }
    2973             : 
    2974             :         /* initialize string */
    2975       15054 :         mbfl_string_init(&string);
    2976       15054 :         mbfl_string_init(&result);
    2977       15054 :         from_encoding = MBSTRG(current_internal_encoding);
    2978       15054 :         string.no_encoding = from_encoding->no_encoding;
    2979       15054 :         string.no_language = MBSTRG(language);
    2980       15054 :         string.val = (unsigned char *)input;
    2981       15054 :         string.len = length;
    2982             : 
    2983             :         /* pre-conversion encoding */
    2984       15054 :         if (_from_encodings) {
    2985       15041 :                 list = NULL;
    2986       15041 :                 size = 0;
    2987       15041 :                 php_mb_parse_encoding_list(_from_encodings, strlen(_from_encodings), &list, &size, 0 TSRMLS_CC);
    2988       15041 :                 if (size == 1) {
    2989       15032 :                         from_encoding = *list;
    2990       15032 :                         string.no_encoding = from_encoding->no_encoding;
    2991           9 :                 } else if (size > 1) {
    2992             :                         /* auto detect */
    2993           9 :                         from_encoding = mbfl_identify_encoding2(&string, list, size, MBSTRG(strict_detection));
    2994           9 :                         if (from_encoding) {
    2995           9 :                                 string.no_encoding = from_encoding->no_encoding;
    2996             :                         } else {
    2997           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to detect character encoding");
    2998           0 :                                 from_encoding = &mbfl_encoding_pass;
    2999           0 :                                 to_encoding = from_encoding;
    3000           0 :                                 string.no_encoding = from_encoding->no_encoding;
    3001             :                         }
    3002             :                 } else {
    3003           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal character encoding specified");
    3004             :                 }
    3005       15041 :                 if (list != NULL) {
    3006       15041 :                         efree((void *)list);
    3007             :                 }
    3008             :         }
    3009             : 
    3010             :         /* initialize converter */
    3011       15054 :         convd = mbfl_buffer_converter_new2(from_encoding, to_encoding, string.len);
    3012       15054 :         if (convd == NULL) {
    3013           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create character encoding converter");
    3014           0 :                 return NULL;
    3015             :         }
    3016       15054 :         mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
    3017       15054 :         mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
    3018             : 
    3019             :         /* do it */
    3020       15054 :         ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
    3021       15054 :         if (ret) {
    3022       15054 :                 if (output_len) {
    3023       15054 :                         *output_len = ret->len;
    3024             :                 }
    3025       15054 :                 output = (char *)ret->val;
    3026             :         }
    3027             : 
    3028       15054 :         MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
    3029       15054 :         mbfl_buffer_converter_delete(convd);
    3030       15054 :         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       12717 : 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       12717 :         char *_from_encodings = NULL, *ret, *s_free = NULL;
    3044             : 
    3045             :         zval **hash_entry;
    3046             :         HashTable *target_hash;
    3047             : 
    3048       12717 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|z", &arg_str, &str_len, &arg_new, &new_len, &arg_old) == FAILURE) {
    3049           2 :                 return;
    3050             :         }
    3051             : 
    3052       12715 :         if (ZEND_NUM_ARGS() == 3) {
    3053       12701 :                 switch (Z_TYPE_P(arg_old)) {
    3054             :                 case IS_ARRAY:
    3055           3 :                         target_hash = Z_ARRVAL_P(arg_old);
    3056           3 :                         zend_hash_internal_pointer_reset(target_hash);
    3057           3 :                         i = zend_hash_num_elements(target_hash);
    3058           3 :                         _from_encodings = NULL;
    3059             : 
    3060          18 :                         while (i > 0) {
    3061          12 :                                 if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) {
    3062           0 :                                         break;
    3063             :                                 }
    3064             : 
    3065          12 :                                 convert_to_string_ex(hash_entry);
    3066             : 
    3067          12 :                                 if ( _from_encodings) {
    3068           9 :                                         l = strlen(_from_encodings);
    3069           9 :                                         n = strlen(Z_STRVAL_PP(hash_entry));
    3070           9 :                                         _from_encodings = erealloc(_from_encodings, l+n+2);
    3071           9 :                                         strcpy(_from_encodings+l, ",");
    3072           9 :                                         strcpy(_from_encodings+l+1, Z_STRVAL_PP(hash_entry));
    3073             :                                 } else {
    3074           3 :                                         _from_encodings = estrdup(Z_STRVAL_PP(hash_entry));
    3075             :                                 }
    3076             : 
    3077          12 :                                 zend_hash_move_forward(target_hash);
    3078          12 :                                 i--;
    3079             :                         }
    3080             : 
    3081           3 :                         if (_from_encodings != NULL && !strlen(_from_encodings)) {
    3082           0 :                                 efree(_from_encodings);
    3083           0 :                                 _from_encodings = NULL;
    3084             :                         }
    3085           3 :                         s_free = _from_encodings;
    3086           3 :                         break;
    3087             :                 default:
    3088       12698 :                         convert_to_string(arg_old);
    3089       12698 :                         _from_encodings = Z_STRVAL_P(arg_old);
    3090             :                         break;
    3091             :                 }
    3092             :         }
    3093             : 
    3094             :         /* new encoding */
    3095       12715 :         ret = php_mb_convert_encoding(arg_str, str_len, arg_new, _from_encodings, &size TSRMLS_CC);
    3096       12715 :         if (ret != NULL) {
    3097       12702 :                 RETVAL_STRINGL(ret, size, 0);           /* the string is already strdup()'ed */
    3098             :         } else {
    3099          13 :                 RETVAL_FALSE;
    3100             :         }
    3101             : 
    3102       12715 :         if ( s_free) {
    3103           3 :                 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           1 : PHP_FUNCTION(mb_convert_case)
    3111             : {
    3112           1 :         const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
    3113             :         char *str;
    3114             :         int str_len, from_encoding_len;
    3115           1 :         long case_mode = 0;
    3116             :         char *newstr;
    3117             :         size_t ret_len;
    3118             : 
    3119           1 :         RETVAL_FALSE;
    3120           1 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|s!", &str, &str_len,
    3121             :                                 &case_mode, &from_encoding, &from_encoding_len) == FAILURE)
    3122           0 :                 RETURN_FALSE;
    3123             : 
    3124           1 :         newstr = php_unicode_convert_case(case_mode, str, (size_t) str_len, &ret_len, from_encoding TSRMLS_CC);
    3125             : 
    3126           1 :         if (newstr) {
    3127           1 :                 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          68 : PHP_FUNCTION(mb_strtoupper)
    3136             : {
    3137          68 :         const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
    3138             :         char *str;
    3139             :         int str_len, from_encoding_len;
    3140             :         char *newstr;
    3141             :         size_t ret_len;
    3142             : 
    3143          68 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &str, &str_len,
    3144             :                                 &from_encoding, &from_encoding_len) == FAILURE) {
    3145           4 :                 return;
    3146             :         }
    3147          64 :         newstr = php_unicode_convert_case(PHP_UNICODE_CASE_UPPER, str, (size_t) str_len, &ret_len, from_encoding TSRMLS_CC);
    3148             : 
    3149          64 :         if (newstr) {
    3150          39 :                 RETURN_STRINGL(newstr, ret_len, 0);
    3151             :         }
    3152          25 :         RETURN_FALSE;
    3153             : }
    3154             : /* }}} */
    3155             : 
    3156             : /* {{{ proto string mb_strtolower(string sourcestring [, string encoding])
    3157             :  *  Returns a lowercased version of sourcestring
    3158             :  */
    3159          65 : PHP_FUNCTION(mb_strtolower)
    3160             : {
    3161          65 :         const char *from_encoding = MBSTRG(current_internal_encoding)->mime_name;
    3162             :         char *str;
    3163             :         int str_len, from_encoding_len;
    3164             :         char *newstr;
    3165             :         size_t ret_len;
    3166             : 
    3167          65 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!", &str, &str_len,
    3168             :                                 &from_encoding, &from_encoding_len) == FAILURE) {
    3169           4 :                 return;
    3170             :         }
    3171          61 :         newstr = php_unicode_convert_case(PHP_UNICODE_CASE_LOWER, str, (size_t) str_len, &ret_len, from_encoding TSRMLS_CC);
    3172             : 
    3173          61 :         if (newstr) {
    3174          36 :                 RETURN_STRINGL(newstr, ret_len, 0);
    3175             :         }
    3176          25 :         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          18 : PHP_FUNCTION(mb_detect_encoding)
    3183             : {
    3184             :         char *str;
    3185             :         int str_len;
    3186          18 :         zend_bool strict=0;
    3187             :         zval *encoding_list;
    3188             : 
    3189             :         mbfl_string string;
    3190             :         const mbfl_encoding *ret;
    3191             :         const mbfl_encoding **elist, **list;
    3192             :         size_t size;
    3193             : 
    3194          18 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zb", &str, &str_len, &encoding_list, &strict) == FAILURE) {
    3195           1 :                 return;
    3196             :         }
    3197             : 
    3198             :         /* make encoding list */
    3199          17 :         list = NULL;
    3200          17 :         size = 0;
    3201          17 :         if (ZEND_NUM_ARGS() >= 2 && !ZVAL_IS_NULL(encoding_list)) {
    3202          14 :                 switch (Z_TYPE_P(encoding_list)) {
    3203             :                 case IS_ARRAY:
    3204           3 :                         if (FAILURE == php_mb_parse_encoding_array(encoding_list, &list, &size, 0 TSRMLS_CC)) {
    3205           0 :                                 if (list) {
    3206           0 :                                         efree(list);
    3207           0 :                                         list = NULL;
    3208           0 :                                         size = 0;
    3209             :                                 }
    3210             :                         }
    3211           3 :                         break;
    3212             :                 default:
    3213          11 :                         convert_to_string(encoding_list);
    3214          11 :                         if (FAILURE == php_mb_parse_encoding_list(Z_STRVAL_P(encoding_list), Z_STRLEN_P(encoding_list), &list, &size, 0 TSRMLS_CC)) {
    3215           0 :                                 if (list) {
    3216           0 :                                         efree(list);
    3217           0 :                                         list = NULL;
    3218           0 :                                         size = 0;
    3219             :                                 }
    3220             :                         }
    3221             :                         break;
    3222             :                 }
    3223          14 :                 if (size <= 0) {
    3224           1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Illegal argument");
    3225             :                 }
    3226             :         }
    3227             : 
    3228          17 :         if (ZEND_NUM_ARGS() < 3) {
    3229          13 :                 strict = (zend_bool)MBSTRG(strict_detection);
    3230             :         }
    3231             : 
    3232          30 :         if (size > 0 && list != NULL) {
    3233          13 :                 elist = list;
    3234             :         } else {
    3235           4 :                 elist = MBSTRG(current_detect_order_list);
    3236           4 :                 size = MBSTRG(current_detect_order_list_size);
    3237             :         }
    3238             : 
    3239          17 :         mbfl_string_init(&string);
    3240          17 :         string.no_language = MBSTRG(language);
    3241          17 :         string.val = (unsigned char *)str;
    3242          17 :         string.len = str_len;
    3243          17 :         ret = mbfl_identify_encoding2(&string, elist, size, strict);
    3244             : 
    3245          17 :         if (list != NULL) {
    3246          13 :                 efree((void *)list);
    3247             :         }
    3248             : 
    3249          17 :         if (ret == NULL) {
    3250           3 :                 RETURN_FALSE;
    3251             :         }
    3252             : 
    3253          14 :         RETVAL_STRING((char *)ret->name, 1);
    3254             : }
    3255             : /* }}} */
    3256             : 
    3257             : /* {{{ proto mixed mb_list_encodings()
    3258             :    Returns an array of all supported entity encodings */
    3259           4 : PHP_FUNCTION(mb_list_encodings)
    3260             : {
    3261             :         const mbfl_encoding **encodings;
    3262             :         const mbfl_encoding *encoding;
    3263             :         int i;
    3264             : 
    3265           4 :         array_init(return_value);
    3266           4 :         i = 0;
    3267           4 :         encodings = mbfl_get_supported_encodings();
    3268         356 :         while ((encoding = encodings[i++]) != NULL) {
    3269         348 :                 add_next_index_string(return_value, (char *) encoding->name, 1);
    3270             :         }
    3271           4 : }
    3272             : /* }}} */
    3273             : 
    3274             : /* {{{ proto array mb_encoding_aliases(string encoding)
    3275             :    Returns an array of the aliases of a given encoding name */
    3276           4 : PHP_FUNCTION(mb_encoding_aliases)
    3277             : {
    3278             :         const mbfl_encoding *encoding;
    3279           4 :         char *name = NULL;
    3280             :         int name_len;
    3281             : 
    3282           4 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
    3283           1 :                 RETURN_FALSE;
    3284             :         }
    3285             : 
    3286           3 :         encoding = mbfl_name2encoding(name);
    3287           3 :         if (!encoding) {
    3288           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", name);
    3289           0 :                 RETURN_FALSE;
    3290             :         }
    3291             : 
    3292           3 :         array_init(return_value);
    3293           3 :         if (encoding->aliases != NULL) {
    3294             :                 const char **alias;
    3295          14 :                 for (alias = *encoding->aliases; *alias; ++alias) {
    3296          12 :                         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         341 : PHP_FUNCTION(mb_encode_mimeheader)
    3305             : {
    3306             :         enum mbfl_no_encoding charset, transenc;
    3307             :         mbfl_string  string, result, *ret;
    3308         341 :         char *charset_name = NULL;
    3309             :         int charset_name_len;
    3310         341 :         char *trans_enc_name = NULL;
    3311             :         int trans_enc_name_len;
    3312         341 :         char *linefeed = "\r\n";
    3313             :         int linefeed_len;
    3314         341 :         long indent = 0;
    3315             : 
    3316         341 :         mbfl_string_init(&string);
    3317         341 :         string.no_language = MBSTRG(language);
    3318         341 :         string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    3319             : 
    3320         341 :         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          11 :                 return;
    3322             :         }
    3323             : 
    3324         330 :         charset = mbfl_no_encoding_pass;
    3325         330 :         transenc = mbfl_no_encoding_base64;
    3326             : 
    3327         330 :         if (charset_name != NULL) {
    3328         330 :                 charset = mbfl_name2no_encoding(charset_name);
    3329         330 :                 if (charset == mbfl_no_encoding_invalid) {
    3330          19 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", charset_name);
    3331          19 :                         RETURN_FALSE;
    3332             :                 }
    3333             :         } else {
    3334           0 :                 const mbfl_language *lang = mbfl_no2language(MBSTRG(language));
    3335           0 :                 if (lang != NULL) {
    3336           0 :                         charset = lang->mail_charset;
    3337           0 :                         transenc = lang->mail_header_encoding;
    3338             :                 }
    3339             :         }
    3340             : 
    3341         311 :         if (trans_enc_name != NULL) {
    3342         490 :                 if (*trans_enc_name == 'B' || *trans_enc_name == 'b') {
    3343         179 :                         transenc = mbfl_no_encoding_base64;
    3344         132 :                 } else if (*trans_enc_name == 'Q' || *trans_enc_name == 'q') {
    3345         109 :                         transenc = mbfl_no_encoding_qprint;
    3346             :                 }
    3347             :         }
    3348             : 
    3349         311 :         mbfl_string_init(&result);
    3350         311 :         ret = mbfl_mime_header_encode(&string, &result, charset, transenc, linefeed, indent);
    3351         311 :         if (ret != NULL) {
    3352         311 :                 RETVAL_STRINGL((char *)ret->val, ret->len, 0);    /* the string is already strdup()'ed */
    3353             :         } else {
    3354           0 :                 RETVAL_FALSE;
    3355             :         }
    3356             : }
    3357             : /* }}} */
    3358             : 
    3359             : /* {{{ proto string mb_decode_mimeheader(string string)
    3360             :    Decodes the MIME "encoded-word" in the string */
    3361          39 : PHP_FUNCTION(mb_decode_mimeheader)
    3362             : {
    3363             :         mbfl_string string, result, *ret;
    3364             : 
    3365          39 :         mbfl_string_init(&string);
    3366          39 :         string.no_language = MBSTRG(language);
    3367          39 :         string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    3368             : 
    3369          39 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", (char **)&string.val, &string.len) == FAILURE) {
    3370           8 :                 return;
    3371             :         }
    3372             : 
    3373          31 :         mbfl_string_init(&result);
    3374          31 :         ret = mbfl_mime_header_decode(&string, &result, MBSTRG(current_internal_encoding)->no_encoding);
    3375          31 :         if (ret != NULL) {
    3376          31 :                 RETVAL_STRINGL((char *)ret->val, ret->len, 0);    /* the string is already strdup()'ed */
    3377             :         } else {
    3378           0 :                 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          10 : PHP_FUNCTION(mb_convert_kana)
    3386             : {
    3387             :         int opt, i;
    3388             :         mbfl_string string, result, *ret;
    3389          10 :         char *optstr = NULL;
    3390             :         int optstr_len;
    3391          10 :         char *encname = NULL;
    3392             :         int encname_len;
    3393             : 
    3394          10 :         mbfl_string_init(&string);
    3395          10 :         string.no_language = MBSTRG(language);
    3396          10 :         string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    3397             : 
    3398          10 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ss", (char **)&string.val, &string.len, &optstr, &optstr_len, &encname, &encname_len) == FAILURE) {
    3399           0 :                 return;
    3400             :         }
    3401             : 
    3402             :         /* option */
    3403          10 :         if (optstr != NULL) {
    3404          10 :                 char *p = optstr;
    3405          10 :                 int n = optstr_len;
    3406          10 :                 i = 0;
    3407          10 :                 opt = 0;
    3408          60 :                 while (i < n) {
    3409          40 :                         i++;
    3410          40 :                         switch (*p++) {
    3411             :                         case 'A':
    3412           5 :                                 opt |= 0x1;
    3413           5 :                                 break;
    3414             :                         case 'a':
    3415           5 :                                 opt |= 0x10;
    3416           5 :                                 break;
    3417             :                         case 'R':
    3418           0 :                                 opt |= 0x2;
    3419           0 :                                 break;
    3420             :                         case 'r':
    3421           0 :                                 opt |= 0x20;
    3422           0 :                                 break;
    3423             :                         case 'N':
    3424           0 :                                 opt |= 0x4;
    3425           0 :                                 break;
    3426             :                         case 'n':
    3427           0 :                                 opt |= 0x40;
    3428           0 :                                 break;
    3429             :                         case 'S':
    3430           0 :                                 opt |= 0x8;
    3431           0 :                                 break;
    3432             :                         case 's':
    3433           0 :                                 opt |= 0x80;
    3434           0 :                                 break;
    3435             :                         case 'K':
    3436           5 :                                 opt |= 0x100;
    3437           5 :                                 break;
    3438             :                         case 'k':
    3439           5 :                                 opt |= 0x1000;
    3440           5 :                                 break;
    3441             :                         case 'H':
    3442           5 :                                 opt |= 0x200;
    3443           5 :                                 break;
    3444             :                         case 'h':
    3445           5 :                                 opt |= 0x2000;
    3446           5 :                                 break;
    3447             :                         case 'V':
    3448           0 :                                 opt |= 0x800;
    3449           0 :                                 break;
    3450             :                         case 'C':
    3451           0 :                                 opt |= 0x10000;
    3452           0 :                                 break;
    3453             :                         case 'c':
    3454           0 :                                 opt |= 0x20000;
    3455           0 :                                 break;
    3456             :                         case 'M':
    3457           0 :                                 opt |= 0x100000;
    3458           0 :                                 break;
    3459             :                         case 'm':
    3460           0 :                                 opt |= 0x200000;
    3461             :                                 break;
    3462             :                         }
    3463             :                 }
    3464             :         } else {
    3465           0 :                 opt = 0x900;
    3466             :         }
    3467             : 
    3468             :         /* encoding */
    3469          10 :         if (encname != NULL) {
    3470          10 :                 string.no_encoding = mbfl_name2no_encoding(encname);
    3471          10 :                 if (string.no_encoding == mbfl_no_encoding_invalid) {
    3472           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encname);
    3473           0 :                         RETURN_FALSE;
    3474             :                 }
    3475             :         }
    3476             : 
    3477          10 :         ret = mbfl_ja_jp_hantozen(&string, &result, opt);
    3478          10 :         if (ret != NULL) {
    3479          10 :                 RETVAL_STRINGL((char *)ret->val, ret->len, 0);            /* the string is already strdup()'ed */
    3480             :         } else {
    3481           0 :                 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          17 : 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;
    3495             :         const mbfl_encoding *from_encoding, *to_encoding;
    3496             :         mbfl_encoding_detector *identd;
    3497             :         mbfl_buffer_converter *convd;
    3498             :         int n, to_enc_len, argc, stack_level, stack_max;
    3499             :         size_t elistsz;
    3500             :         const mbfl_encoding **elist;
    3501             :         char *to_enc;
    3502             :         void *ptmp;     
    3503             : 
    3504          17 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sZ+", &to_enc, &to_enc_len, &zfrom_enc, &args, &argc) == FAILURE) {
    3505           0 :                 return;
    3506             :         }
    3507             : 
    3508             :         /* new encoding */
    3509          17 :         to_encoding = mbfl_name2encoding(to_enc);
    3510          17 :         if (!to_encoding) {
    3511           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", to_enc);
    3512           0 :                 efree(args);
    3513           0 :                 RETURN_FALSE;
    3514             :         }
    3515             : 
    3516             :         /* initialize string */
    3517          17 :         mbfl_string_init(&string);
    3518          17 :         mbfl_string_init(&result);
    3519          17 :         from_encoding = MBSTRG(current_internal_encoding);
    3520          17 :         string.no_encoding = from_encoding->no_encoding;
    3521          17 :         string.no_language = MBSTRG(language);
    3522             : 
    3523             :         /* pre-conversion encoding */
    3524          17 :         elist = NULL;
    3525          17 :         elistsz = 0;
    3526          17 :         switch (Z_TYPE_PP(zfrom_enc)) {
    3527             :         case IS_ARRAY:
    3528           0 :                 php_mb_parse_encoding_array(*zfrom_enc, &elist, &elistsz, 0 TSRMLS_CC);
    3529           0 :                 break;
    3530             :         default:
    3531          17 :                 convert_to_string_ex(zfrom_enc);
    3532          17 :                 php_mb_parse_encoding_list(Z_STRVAL_PP(zfrom_enc), Z_STRLEN_PP(zfrom_enc), &elist, &elistsz, 0 TSRMLS_CC);
    3533             :                 break;
    3534             :         }
    3535          17 :         if (elistsz <= 0) {
    3536           0 :                 from_encoding = &mbfl_encoding_pass;
    3537          17 :         } else if (elistsz == 1) {
    3538          11 :                 from_encoding = *elist;
    3539             :         } else {
    3540             :                 /* auto detect */
    3541           6 :                 from_encoding = NULL;
    3542           6 :                 stack_max = PHP_MBSTR_STACK_BLOCK_SIZE;
    3543           6 :                 stack = (zval ***)safe_emalloc(stack_max, sizeof(zval **), 0);
    3544           6 :                 stack_level = 0;
    3545           6 :                 identd = mbfl_encoding_detector_new2(elist, elistsz, MBSTRG(strict_detection));
    3546           6 :                 if (identd != NULL) {
    3547           6 :                         n = 0;
    3548          12 :                         while (n < argc || stack_level > 0) {
    3549           6 :                                 if (stack_level <= 0) {
    3550           6 :                                         var = args[n++];
    3551           6 :                                         if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
    3552           4 :                                                 target_hash = HASH_OF(*var);
    3553           4 :                                                 if (target_hash != NULL) {
    3554           4 :                                                         zend_hash_internal_pointer_reset(target_hash);
    3555             :                                                 }
    3556             :                                         }
    3557             :                                 } else {
    3558           0 :                                         stack_level--;
    3559           0 :                                         var = stack[stack_level];
    3560             :                                 }
    3561           6 :                                 if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
    3562           4 :                                         target_hash = HASH_OF(*var);
    3563           4 :                                         if (target_hash != NULL) {
    3564           8 :                                                 while (zend_hash_get_current_data(target_hash, (void **) &hash_entry) != FAILURE) {
    3565           4 :                                                         zend_hash_move_forward(target_hash);
    3566           4 :                                                         if (Z_TYPE_PP(hash_entry) == IS_ARRAY || Z_TYPE_PP(hash_entry) == IS_OBJECT) {
    3567           0 :                                                                 if (stack_level >= stack_max) {
    3568           0 :                                                                         stack_max += PHP_MBSTR_STACK_BLOCK_SIZE;
    3569           0 :                                                                         ptmp = erealloc(stack, sizeof(zval **)*stack_max);
    3570           0 :                                                                         stack = (zval ***)ptmp;
    3571             :                                                                 }
    3572           0 :                                                                 stack[stack_level] = var;
    3573           0 :                                                                 stack_level++;
    3574           0 :                                                                 var = hash_entry;
    3575           0 :                                                                 target_hash = HASH_OF(*var);
    3576           0 :                                                                 if (target_hash != NULL) {
    3577           0 :                                                                         zend_hash_internal_pointer_reset(target_hash);
    3578           0 :                                                                         continue;
    3579             :                                                                 }
    3580           4 :                                                         } else if (Z_TYPE_PP(hash_entry) == IS_STRING) {
    3581           4 :                                                                 string.val = (unsigned char *)Z_STRVAL_PP(hash_entry);
    3582           4 :                                                                 string.len = Z_STRLEN_PP(hash_entry);
    3583           4 :                                                                 if (mbfl_encoding_detector_feed(identd, &string)) {
    3584           4 :                                                                         goto detect_end;                /* complete detecting */
    3585             :                                                                 }
    3586             :                                                         }
    3587             :                                                 }
    3588             :                                         }
    3589           2 :                                 } else if (Z_TYPE_PP(var) == IS_STRING) {
    3590           2 :                                         string.val = (unsigned char *)Z_STRVAL_PP(var);
    3591           2 :                                         string.len = Z_STRLEN_PP(var);
    3592           2 :                                         if (mbfl_encoding_detector_feed(identd, &string)) {
    3593           2 :                                                 goto detect_end;                /* complete detecting */
    3594             :                                         }
    3595             :                                 }
    3596             :                         }
    3597             : detect_end:
    3598           6 :                         from_encoding = mbfl_encoding_detector_judge2(identd);
    3599           6 :                         mbfl_encoding_detector_delete(identd);
    3600             :                 }
    3601           6 :                 efree(stack);
    3602             : 
    3603           6 :                 if (!from_encoding) {
    3604           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to detect encoding");
    3605           0 :                         from_encoding = &mbfl_encoding_pass;
    3606             :                 }
    3607             :         }
    3608          17 :         if (elist != NULL) {
    3609          17 :                 efree((void *)elist);
    3610             :         }
    3611             :         /* create converter */
    3612          17 :         convd = NULL;
    3613          17 :         if (from_encoding != &mbfl_encoding_pass) {
    3614          17 :                 convd = mbfl_buffer_converter_new2(from_encoding, to_encoding, 0);
    3615          17 :                 if (convd == NULL) {
    3616           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create converter");
    3617           0 :                         RETURN_FALSE;
    3618             :                 }
    3619          17 :                 mbfl_buffer_converter_illegal_mode(convd, MBSTRG(current_filter_illegal_mode));
    3620          17 :                 mbfl_buffer_converter_illegal_substchar(convd, MBSTRG(current_filter_illegal_substchar));
    3621             :         }
    3622             : 
    3623             :         /* convert */
    3624          17 :         if (convd != NULL) {
    3625          17 :                 stack_max = PHP_MBSTR_STACK_BLOCK_SIZE;
    3626          17 :                 stack = (zval ***)safe_emalloc(stack_max, sizeof(zval **), 0);
    3627          17 :                 stack_level = 0;
    3628          17 :                 n = 0;
    3629          58 :                 while (n < argc || stack_level > 0) {
    3630          24 :                         if (stack_level <= 0) {
    3631          23 :                                 var = args[n++];
    3632          23 :                                 if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
    3633          11 :                                         target_hash = HASH_OF(*var);
    3634          11 :                                         if (target_hash != NULL) {
    3635          11 :                                                 zend_hash_internal_pointer_reset(target_hash);
    3636             :                                         }
    3637             :                                 }
    3638             :                         } else {
    3639           1 :                                 stack_level--;
    3640           1 :                                 var = stack[stack_level];
    3641             :                         }
    3642          36 :                         if (Z_TYPE_PP(var) == IS_ARRAY || Z_TYPE_PP(var) == IS_OBJECT) {
    3643          12 :                                 target_hash = HASH_OF(*var);
    3644          12 :                                 if (target_hash != NULL) {
    3645          48 :                                         while (zend_hash_get_current_data(target_hash, (void **) &hash_entry) != FAILURE) {
    3646          24 :                                                 zend_hash_move_forward(target_hash);
    3647          24 :                                                 if (Z_TYPE_PP(hash_entry) == IS_ARRAY || Z_TYPE_PP(hash_entry) == IS_OBJECT) {
    3648           1 :                                                         if (stack_level >= stack_max) {
    3649           0 :                                                                 stack_max += PHP_MBSTR_STACK_BLOCK_SIZE;
    3650           0 :                                                                 ptmp = erealloc(stack, sizeof(zval **)*stack_max);
    3651           0 :                                                                 stack = (zval ***)ptmp;
    3652             :                                                         }
    3653           1 :                                                         stack[stack_level] = var;
    3654           1 :                                                         stack_level++;
    3655           1 :                                                         var = hash_entry;
    3656           4 :                                                         SEPARATE_ZVAL(hash_entry);
    3657           1 :                                                         target_hash = HASH_OF(*var);
    3658           1 :                                                         if (target_hash != NULL) {
    3659           1 :                                                                 zend_hash_internal_pointer_reset(target_hash);
    3660           1 :                                                                 continue;
    3661             :                                                         }
    3662          23 :                                                 } else if (Z_TYPE_PP(hash_entry) == IS_STRING) {
    3663          23 :                                                         string.val = (unsigned char *)Z_STRVAL_PP(hash_entry);
    3664          23 :                                                         string.len = Z_STRLEN_PP(hash_entry);
    3665          23 :                                                         ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
    3666          23 :                                                         if (ret != NULL) {
    3667          46 :                                                                 if (Z_REFCOUNT_PP(hash_entry) > 1) {
    3668          14 :                                                                         Z_DELREF_PP(hash_entry);
    3669          14 :                                                                         MAKE_STD_ZVAL(*hash_entry);
    3670             :                                                                 } else {
    3671           9 :                                                                         zval_dtor(*hash_entry);
    3672             :                                                                 }
    3673          23 :                                                         ZVAL_STRINGL(*hash_entry, (char *)ret->val, ret->len, 0);
    3674             :                                                 }
    3675             :                                         }
    3676             :                                 }
    3677             :                         }
    3678          12 :                 } else if (Z_TYPE_PP(var) == IS_STRING) {
    3679          12 :                         string.val = (unsigned char *)Z_STRVAL_PP(var);
    3680          12 :                         string.len = Z_STRLEN_PP(var);
    3681          12 :                         ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
    3682          12 :                         if (ret != NULL) {
    3683          12 :                                 zval_dtor(*var);
    3684          12 :                                 ZVAL_STRINGL(*var, (char *)ret->val, ret->len, 0);
    3685             :                                 }
    3686             :                         }
    3687             :                 }
    3688          17 :                 efree(stack);
    3689             : 
    3690          17 :                 MBSTRG(illegalchars) += mbfl_buffer_illegalchars(convd);
    3691          17 :                 mbfl_buffer_converter_delete(convd);
    3692             :         }
    3693             : 
    3694          17 :         efree(args);
    3695             : 
    3696          17 :         if (from_encoding) {
    3697          17 :                 RETURN_STRING(from_encoding->name, 1);
    3698             :         } else {
    3699           0 :                 RETURN_FALSE;
    3700             :         }
    3701             : }
    3702             : /* }}} */
    3703             : 
    3704             : /* {{{ HTML numeric entity */
    3705             : /* {{{ static void php_mb_numericentity_exec() */
    3706             : static void
    3707          14 : 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          14 :         size_t argc = ZEND_NUM_ARGS();
    3714          14 :         int i, *convmap, *mapelm, mapsize=0;
    3715          14 :         zend_bool is_hex = 0;
    3716             :         mbfl_string string, result, *ret;
    3717             :         enum mbfl_no_encoding no_encoding;
    3718             : 
    3719          14 :         if (zend_parse_parameters(argc TSRMLS_CC, "sz|sb", &str, &str_len, &zconvmap, &encoding, &encoding_len, &is_hex) == FAILURE) {
    3720           0 :                 return;
    3721             :         }
    3722             : 
    3723          14 :         mbfl_string_init(&string);
    3724          14 :         string.no_language = MBSTRG(language);
    3725          14 :         string.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    3726          14 :         string.val = (unsigned char *)str;
    3727          14 :         string.len = str_len;
    3728             : 
    3729             :         /* encoding */
    3730          14 :         if ((argc == 3 || argc == 4) && encoding_len > 0) {
    3731          14 :                 no_encoding = mbfl_name2no_encoding(encoding);
    3732          14 :                 if (no_encoding == mbfl_no_encoding_invalid) {
    3733           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", encoding);
    3734           0 :                         RETURN_FALSE;
    3735             :                 } else {
    3736          14 :                         string.no_encoding = no_encoding;
    3737             :                 }
    3738             :         }
    3739             : 
    3740          14 :         if (argc == 4) {
    3741           0 :                 if (type == 0 && is_hex) {
    3742           0 :                         type = 2; /* output in hex format */
    3743             :                 }
    3744             :         }
    3745             : 
    3746             :         /* conversion map */
    3747          14 :         convmap = NULL;
    3748          14 :         if (Z_TYPE_P(zconvmap) == IS_ARRAY) {
    3749          14 :                 target_hash = Z_ARRVAL_P(zconvmap);
    3750          14 :                 zend_hash_internal_pointer_reset(target_hash);
    3751          14 :                 i = zend_hash_num_elements(target_hash);
    3752          14 :                 if (i > 0) {
    3753          14 :                         convmap = (int *)safe_emalloc(i, sizeof(int), 0);
    3754          14 :                         mapelm = convmap;
    3755          14 :                         mapsize = 0;
    3756          84 :                         while (i > 0) {
    3757          56 :                                 if (zend_hash_get_current_data(target_hash, (void **) &hash_entry) == FAILURE) {
    3758           0 :                                         break;
    3759             :                                 }
    3760          56 :                                 convert_to_long_ex(hash_entry);
    3761          56 :                                 *mapelm++ = Z_LVAL_PP(hash_entry);
    3762          56 :                                 mapsize++;
    3763          56 :                                 i--;
    3764          56 :                                 zend_hash_move_forward(target_hash);
    3765             :                         }
    3766             :                 }
    3767             :         }
    3768          14 :         if (convmap == NULL) {
    3769           0 :                 RETURN_FALSE;
    3770             :         }
    3771          14 :         mapsize /= 4;
    3772             : 
    3773          14 :         ret = mbfl_html_numeric_entity(&string, &result, convmap, mapsize, type);
    3774          14 :         if (ret != NULL) {
    3775          14 :                 RETVAL_STRINGL((char *)ret->val, ret->len, 0);
    3776             :         } else {
    3777           0 :                 RETVAL_FALSE;
    3778             :         }
    3779          14 :         efree((void *)convmap);
    3780             : }
    3781             : /* }}} */
    3782             : 
    3783             : /* {{{ proto string mb_encode_numericentity(string string, array convmap [, string encoding [, bool is_hex]])
    3784             :    Converts specified characters to HTML numeric entities */
    3785           3 : PHP_FUNCTION(mb_encode_numericentity)
    3786             : {
    3787           3 :         php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    3788           3 : }
    3789             : /* }}} */
    3790             : 
    3791             : /* {{{ proto string mb_decode_numericentity(string string, array convmap [, string encoding])
    3792             :    Converts HTML numeric entities to character code */
    3793          11 : PHP_FUNCTION(mb_decode_numericentity)
    3794             : {
    3795          11 :         php_mb_numericentity_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    3796          11 : }
    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           2 : static void my_smart_str_dtor(smart_str *s)
    3842             : {
    3843           2 :         if (s->a > 0) {
    3844           1 :                 smart_str_free(s);
    3845             :         }
    3846           2 : }
    3847             : 
    3848           1 : 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           1 :         int state = 0;
    3853           1 :         int crlf_state = -1;
    3854             : 
    3855           1 :         smart_str token = { 0, 0, 0 };
    3856           1 :         smart_str fld_name = { 0, 0, 0 }, fld_val = { 0, 0, 0 };
    3857             : 
    3858           1 :         ps = str;
    3859           1 :         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          19 :         while (icnt > 0) {
    3873          17 :                 switch (*ps) {
    3874             :                         case ':':
    3875           1 :                                 if (crlf_state == 1) {
    3876           0 :                                         APPEND_ONE_CHAR('\r');
    3877             :                                 }
    3878             : 
    3879           2 :                                 if (state == 0 || state == 1) {
    3880           1 :                                         fld_name = token;
    3881             : 
    3882           1 :                                         state = 2;
    3883             :                                 } else {
    3884           0 :                                         APPEND_ONE_CHAR(*ps);
    3885             :                                 }
    3886             : 
    3887           1 :                                 crlf_state = 0;
    3888           1 :                                 break;
    3889             : 
    3890             :                         case '\n':
    3891           0 :                                 if (crlf_state == -1) {
    3892           0 :                                         goto out;
    3893             :                                 }
    3894           0 :                                 crlf_state = -1;
    3895           0 :                                 break;
    3896             : 
    3897             :                         case '\r':
    3898           0 :                                 if (crlf_state == 1) {
    3899           0 :                                         APPEND_ONE_CHAR('\r');
    3900             :                                 } else {
    3901           0 :                                         crlf_state = 1;
    3902             :                                 }
    3903           0 :                                 break;
    3904             : 
    3905             :                         case ' ': case '\t':
    3906           1 :                                 if (crlf_state == -1) {
    3907           0 :                                         if (state == 3) {
    3908             :                                                 /* continuing from the previous line */
    3909           0 :                                                 SEPARATE_SMART_STR(&token);
    3910           0 :                                                 state = 4;
    3911             :                                         } else {
    3912             :                                                 /* simply skipping this new line */
    3913           0 :                                                 state = 5;
    3914             :                                         }
    3915             :                                 } else {
    3916           1 :                                         if (crlf_state == 1) {
    3917           0 :                                                 APPEND_ONE_CHAR('\r');
    3918             :                                         }
    3919           1 :                                         if (state == 1 || state == 3) {
    3920           0 :                                                 APPEND_ONE_CHAR(*ps);
    3921             :                                         }
    3922             :                                 }
    3923           1 :                                 crlf_state = 0;
    3924           1 :                                 break;
    3925             : 
    3926             :                         default:
    3927          15 :                                 switch (state) {
    3928             :                                         case 0:
    3929           1 :                                                 token.c = (char *)ps;
    3930           1 :                                                 token.len = 0;
    3931           1 :                                                 token.a = 0;
    3932           1 :                                                 state = 1;
    3933           1 :                                                 break;
    3934             :                                         
    3935             :                                         case 2:
    3936           1 :                                                 if (crlf_state != -1) {
    3937           1 :                                                         token.c = (char *)ps;
    3938           1 :                                                         token.len = 0;
    3939           1 :                                                         token.a = 0;
    3940             : 
    3941           1 :                                                         state = 3;
    3942           1 :                                                         break;
    3943             :                                                 }
    3944             :                                                 /* break is missing intentionally */
    3945             : 
    3946             :                                         case 3:
    3947           2 :                                                 if (crlf_state == -1) {
    3948           0 :                                                         fld_val = token;
    3949             : 
    3950           0 :                                                         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           0 :                                                                 SEPARATE_SMART_STR(&fld_name);
    3956           0 :                                                                 php_strtoupper(fld_name.c, fld_name.len);
    3957             : 
    3958           0 :                                                                 zend_hash_update(ht, (char *)fld_name.c, fld_name.len, &fld_val, sizeof(smart_str), (void **)&dummy);
    3959             : 
    3960           0 :                                                                 my_smart_str_dtor(&fld_name);
    3961             :                                                         }
    3962             : 
    3963           0 :                                                         memset(&fld_name, 0, sizeof(smart_str));
    3964           0 :                                                         memset(&fld_val, 0, sizeof(smart_str));
    3965             : 
    3966           0 :                                                         token.c = (char *)ps;
    3967           0 :                                                         token.len = 0;
    3968           0 :                                                         token.a = 0;
    3969             : 
    3970           0 :                                                         state = 1;
    3971             :                                                 }
    3972           2 :                                                 break;
    3973             : 
    3974             :                                         case 4:
    3975           0 :                                                 APPEND_ONE_CHAR(' ');
    3976           0 :                                                 state = 3;
    3977             :                                                 break;
    3978             :                                 }
    3979             : 
    3980          15 :                                 if (crlf_state == 1) {
    3981           0 :                                         APPEND_ONE_CHAR('\r');
    3982             :                                 }
    3983             : 
    3984          15 :                                 APPEND_ONE_CHAR(*ps);
    3985             : 
    3986          15 :                                 crlf_state = 0;
    3987             :                                 break;
    3988             :                 }
    3989          17 :                 ps++, icnt--;
    3990             :         }
    3991             : out:
    3992           1 :         if (state == 2) {
    3993           0 :                 token.c = "";
    3994           0 :                 token.len = 0;
    3995           0 :                 token.a = 0;
    3996             : 
    3997           0 :                 state = 3;
    3998             :         }
    3999           1 :         if (state == 3) {
    4000           1 :                 fld_val = token;
    4001             : 
    4002           1 :                 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           1 :                         SEPARATE_SMART_STR(&fld_name);
    4008           1 :                         php_strtoupper(fld_name.c, fld_name.len);
    4009             : 
    4010           1 :                         zend_hash_update(ht, (char *)fld_name.c, fld_name.len, &fld_val, sizeof(smart_str), (void **)&dummy);
    4011             : 
    4012           1 :                         my_smart_str_dtor(&fld_name);
    4013             :                 }
    4014             :         }
    4015           1 :         return state;
    4016             : }
    4017             : 
    4018          15 : PHP_FUNCTION(mb_send_mail)
    4019             : {
    4020             :         int n;
    4021          15 :         char *to = NULL;
    4022             :         int to_len;
    4023          15 :         char *message = NULL;
    4024             :         int message_len;
    4025          15 :         char *headers = NULL;
    4026             :         int headers_len;
    4027          15 :         char *subject = NULL;
    4028             :         int subject_len;
    4029          15 :         char *extra_cmd = NULL;
    4030             :         int extra_cmd_len;
    4031             :         int i;
    4032          15 :         char *to_r = NULL;
    4033          15 :         char *force_extra_parameters = INI_STR("mail.force_extra_parameters");
    4034             :         struct {
    4035             :                 int cnt_type:1;
    4036             :                 int cnt_trans_enc:1;
    4037          15 :         } suppressed_hdrs = { 0, 0 };
    4038             : 
    4039          15 :         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
    4043             :                 tran_cs,        /* transfar text charset */
    4044             :                 head_enc,       /* header transfar encoding */
    4045             :                 body_enc;       /* body transfar encoding */
    4046             :         mbfl_memory_device device;      /* automatic allocateable buffer for additional header */
    4047             :         const mbfl_language *lang;
    4048          15 :         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;
    4053             : 
    4054             :         /* initialize */
    4055          15 :         mbfl_memory_device_init(&device, 0, 0);
    4056          15 :         mbfl_string_init(&orig_str);
    4057          15 :         mbfl_string_init(&conv_str);
    4058             : 
    4059             :         /* character-set, transfer-encoding */
    4060          15 :         tran_cs = mbfl_no_encoding_utf8;
    4061          15 :         head_enc = mbfl_no_encoding_base64;
    4062          15 :         body_enc = mbfl_no_encoding_base64;
    4063          15 :         lang = mbfl_no2language(MBSTRG(language));
    4064          15 :         if (lang != NULL) {
    4065          15 :                 tran_cs = lang->mail_charset;
    4066          15 :                 head_enc = lang->mail_header_encoding;
    4067          15 :                 body_enc = lang->mail_body_encoding;
    4068             :         }
    4069             : 
    4070          15 :         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           0 :                 return;
    4072             :         }
    4073             : 
    4074             :         /* ASCIIZ check */
    4075          15 :         MAIL_ASCIIZ_CHECK_MBSTRING(to, to_len);
    4076          15 :         MAIL_ASCIIZ_CHECK_MBSTRING(subject, subject_len);
    4077          15 :         MAIL_ASCIIZ_CHECK_MBSTRING(message, message_len);
    4078          15 :         if (headers) {
    4079           1 :                 MAIL_ASCIIZ_CHECK_MBSTRING(headers, headers_len);
    4080             :         }
    4081          15 :         if (extra_cmd) {
    4082           0 :                 MAIL_ASCIIZ_CHECK_MBSTRING(extra_cmd, extra_cmd_len);
    4083             :         }
    4084             : 
    4085          15 :         zend_hash_init(&ht_headers, 0, NULL, (dtor_func_t) my_smart_str_dtor, 0);
    4086             : 
    4087          15 :         if (headers != NULL) {
    4088           1 :                 _php_mbstr_parse_mail_headers(&ht_headers, headers, headers_len);
    4089             :         }
    4090             : 
    4091          15 :         if (zend_hash_find(&ht_headers, "CONTENT-TYPE", sizeof("CONTENT-TYPE") - 1, (void **)&s) == SUCCESS) {
    4092             :                 char *tmp;
    4093             :                 char *param_name;
    4094           0 :                 char *charset = NULL;
    4095             : 
    4096           0 :                 SEPARATE_SMART_STR(s);
    4097           0 :                 smart_str_0(s);
    4098             : 
    4099           0 :                 p = strchr(s->c, ';');
    4100             : 
    4101           0 :                 if (p != NULL) {
    4102             :                         /* skipping the padded spaces */
    4103             :                         do {
    4104           0 :                                 ++p;
    4105           0 :                         } while (*p == ' ' || *p == '\t');
    4106             : 
    4107           0 :                         if (*p != '\0') {
    4108           0 :                                 if ((param_name = php_strtok_r(p, "= ", &tmp)) != NULL) {
    4109           0 :                                         if (strcasecmp(param_name, "charset") == 0) {
    4110           0 :                                                 enum mbfl_no_encoding _tran_cs = tran_cs;
    4111             :                                                 
    4112           0 :                                                 charset = php_strtok_r(NULL, "= \"", &tmp);
    4113           0 :                                                 if (charset != NULL) {
    4114           0 :                                                         _tran_cs = mbfl_name2no_encoding(charset);
    4115             :                                                 }
    4116             : 
    4117           0 :                                                 if (_tran_cs == mbfl_no_encoding_invalid) {
    4118           0 :                                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported charset \"%s\" - will be regarded as ascii", charset); 
    4119           0 :                                                         _tran_cs = mbfl_no_encoding_ascii;
    4120             :                                                 }
    4121           0 :                                                 tran_cs = _tran_cs;
    4122             :                                         }
    4123             :                                 }
    4124             :                         }
    4125             :                 }
    4126           0 :                 suppressed_hdrs.cnt_type = 1;
    4127             :         }
    4128             : 
    4129          15 :         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           0 :                 SEPARATE_SMART_STR(s);
    4132           0 :                 smart_str_0(s);
    4133             : 
    4134           0 :                 _body_enc = mbfl_name2no_encoding(s->c);
    4135           0 :                 switch (_body_enc) {
    4136             :                         case mbfl_no_encoding_base64:
    4137             :                         case mbfl_no_encoding_7bit:
    4138             :                         case mbfl_no_encoding_8bit:
    4139           0 :                                 body_enc = _body_enc;
    4140           0 :                                 break;
    4141             : 
    4142             :                         default:
    4143           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported transfer encoding \"%s\" - will be regarded as 8bit", s->c); 
    4144           0 :                                 body_enc =      mbfl_no_encoding_8bit;
    4145             :                                 break;
    4146             :                 }
    4147           0 :                 suppressed_hdrs.cnt_trans_enc = 1;
    4148             :         }
    4149             : 
    4150             :         /* To: */
    4151          15 :         if (to != NULL) {
    4152          15 :                 if (to_len > 0) {
    4153          15 :                         to_r = estrndup(to, to_len);
    4154          15 :                         for (; to_len; to_len--) {
    4155          15 :                                 if (!isspace((unsigned char) to_r[to_len - 1])) {
    4156          15 :                                         break;
    4157             :                                 }
    4158           0 :                                 to_r[to_len - 1] = '\0';
    4159             :                         }
    4160         300 :                         for (i = 0; to_r[i]; i++) {
    4161         285 :                         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           0 :                                 SKIP_LONG_HEADER_SEP_MBSTRING(to_r, i);
    4168           0 :                                 to_r[i] = ' ';
    4169             :                         }
    4170             :                         }
    4171             :                 } else {
    4172           0 :                         to_r = to;
    4173             :                 }
    4174             :         } else {
    4175           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing To: field");
    4176           0 :                 err = 1;
    4177             :         }
    4178             : 
    4179             :         /* Subject: */
    4180          30 :         if (subject != NULL && subject_len >= 0) {
    4181          15 :                 orig_str.no_language = MBSTRG(language);
    4182          15 :                 orig_str.val = (unsigned char *)subject;
    4183          15 :                 orig_str.len = subject_len;
    4184          15 :                 orig_str.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    4185          15 :                 if (orig_str.no_encoding == mbfl_no_encoding_invalid || orig_str.no_encoding == mbfl_no_encoding_pass) {
    4186           1 :                         const mbfl_encoding *encoding = mbfl_identify_encoding2(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection));
    4187           1 :                         orig_str.no_encoding = encoding ? encoding->no_encoding: mbfl_no_encoding_invalid;
    4188             :                 }
    4189          15 :                 pstr = mbfl_mime_header_encode(&orig_str, &conv_str, tran_cs, head_enc, "\n", sizeof("Subject: [PHP-jp nnnnnnnn]"));
    4190          15 :                 if (pstr != NULL) {
    4191          15 :                         subject_buf = subject = (char *)pstr->val;
    4192             :                 }
    4193             :         } else {
    4194           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing Subject: field");
    4195           0 :                 err = 1;
    4196             :         }
    4197             : 
    4198             :         /* message body */
    4199          15 :         if (message != NULL) {
    4200          15 :                 orig_str.no_language = MBSTRG(language);
    4201          15 :                 orig_str.val = (unsigned char *)message;
    4202          15 :                 orig_str.len = (unsigned int)message_len;
    4203          15 :                 orig_str.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    4204             : 
    4205          15 :                 if (orig_str.no_encoding == mbfl_no_encoding_invalid || orig_str.no_encoding == mbfl_no_encoding_pass) {
    4206           1 :                         const mbfl_encoding *encoding = mbfl_identify_encoding2(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection));
    4207           1 :                         orig_str.no_encoding = encoding ? encoding->no_encoding: mbfl_no_encoding_invalid;
    4208             :                 }
    4209             : 
    4210          15 :                 pstr = NULL;
    4211             :                 {
    4212             :                         mbfl_string tmpstr;
    4213             : 
    4214          15 :                         if (mbfl_convert_encoding(&orig_str, &tmpstr, tran_cs) != NULL) {
    4215          15 :                                 tmpstr.no_encoding=mbfl_no_encoding_8bit;
    4216          15 :                                 pstr = mbfl_convert_encoding(&tmpstr, &conv_str, body_enc);
    4217          15 :                                 efree(tmpstr.val);
    4218             :                         }
    4219             :                 }
    4220          15 :                 if (pstr != NULL) {
    4221          15 :                         message_buf = message = (char *)pstr->val;
    4222             :                 }
    4223             :         } else {
    4224             :                 /* this is not really an error, so it is allowed. */
    4225           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty message body");
    4226           0 :                 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          15 :         if (headers != NULL) {
    4235           1 :                 p = headers;
    4236           1 :                 n = headers_len;
    4237           1 :                 mbfl_memory_device_strncat(&device, p, n);
    4238           1 :                 if (n > 0 && p[n - 1] != '\n') {
    4239           1 :                         mbfl_memory_device_strncat(&device, "\n", 1);
    4240             :                 }
    4241             :         }
    4242             : 
    4243          15 :         if (!zend_hash_exists(&ht_headers, "MIME-VERSION", sizeof("MIME-VERSION") - 1)) {
    4244          14 :                 mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER1, sizeof(PHP_MBSTR_MAIL_MIME_HEADER1) - 1);
    4245          14 :                 mbfl_memory_device_strncat(&device, "\n", 1);
    4246             :         }
    4247             : 
    4248          15 :         if (!suppressed_hdrs.cnt_type) {
    4249          15 :                 mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER2, sizeof(PHP_MBSTR_MAIL_MIME_HEADER2) - 1);
    4250             : 
    4251          15 :                 p = (char *)mbfl_no2preferred_mime_name(tran_cs);
    4252          15 :                 if (p != NULL) {
    4253          15 :                         mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER3, sizeof(PHP_MBSTR_MAIL_MIME_HEADER3) - 1);
    4254          15 :                         mbfl_memory_device_strcat(&device, p);
    4255             :                 }
    4256          15 :                 mbfl_memory_device_strncat(&device, "\n", 1);
    4257             :         }
    4258          15 :         if (!suppressed_hdrs.cnt_trans_enc) {
    4259          15 :                 mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER4, sizeof(PHP_MBSTR_MAIL_MIME_HEADER4) - 1);
    4260          15 :                 p = (char *)mbfl_no2preferred_mime_name(body_enc);
    4261          15 :                 if (p == NULL) {
    4262           0 :                         p = "7bit";
    4263             :                 }
    4264          15 :                 mbfl_memory_device_strcat(&device, p);
    4265          15 :                 mbfl_memory_device_strncat(&device, "\n", 1);
    4266             :         }
    4267             : 
    4268          15 :         mbfl_memory_device_unput(&device);
    4269          15 :         mbfl_memory_device_output('\0', &device);
    4270          15 :         headers = (char *)device.buffer;
    4271             : 
    4272          15 :         if (force_extra_parameters) {
    4273           0 :                 extra_cmd = php_escape_shell_cmd(force_extra_parameters);
    4274          15 :         } else if (extra_cmd) {
    4275           0 :                 extra_cmd = php_escape_shell_cmd(extra_cmd);
    4276             :         } 
    4277             : 
    4278          30 :         if (!err && php_mail(to_r, subject, message, headers, extra_cmd TSRMLS_CC)) {
    4279          15 :                 RETVAL_TRUE;
    4280             :         } else {
    4281           0 :                 RETVAL_FALSE;
    4282             :         }
    4283             : 
    4284          15 :         if (extra_cmd) {
    4285           0 :                 efree(extra_cmd);
    4286             :         }
    4287          15 :         if (to_r != to) {
    4288          15 :                 efree(to_r);
    4289             :         }
    4290          15 :         if (subject_buf) {
    4291          15 :                 efree((void *)subject_buf);
    4292             :         }
    4293          15 :         if (message_buf) {
    4294          15 :                 efree((void *)message_buf);
    4295             :         }
    4296          15 :         mbfl_memory_device_clear(&device);
    4297          15 :         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          16 : PHP_FUNCTION(mb_get_info)
    4313             : {
    4314          16 :         char *typ = NULL;
    4315             :         int typ_len;
    4316             :         size_t n;
    4317             :         char *name;
    4318             :         const struct mb_overload_def *over_func;
    4319             :         zval *row1, *row2;
    4320          16 :         const mbfl_language *lang = mbfl_no2language(MBSTRG(language));
    4321             :         const mbfl_encoding **entry;
    4322             : 
    4323          16 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &typ, &typ_len) == FAILURE) {
    4324           0 :                 RETURN_FALSE;
    4325             :         }
    4326             : 
    4327          17 :         if (!typ || !strcasecmp("all", typ)) {
    4328           1 :                 array_init(return_value);
    4329           1 :                 if (MBSTRG(current_internal_encoding)) {
    4330           1 :                         add_assoc_string(return_value, "internal_encoding", (char *)MBSTRG(current_internal_encoding)->name, 1);
    4331             :                 }
    4332           1 :                 if (MBSTRG(http_input_identify)) {
    4333           1 :                         add_assoc_string(return_value, "http_input", (char *)MBSTRG(http_input_identify)->name, 1);
    4334             :                 }
    4335           1 :                 if (MBSTRG(current_http_output_encoding)) {
    4336           1 :                         add_assoc_string(return_value, "http_output", (char *)MBSTRG(current_http_output_encoding)->name, 1);
    4337             :                 }
    4338           1 :                 if ((name = (char *)zend_ini_string("mbstring.http_output_conv_mimetypes", sizeof("mbstring.http_output_conv_mimetypes"), 0)) != NULL) {
    4339           1 :                         add_assoc_string(return_value, "http_output_conv_mimetypes", name, 1);
    4340             :                 }
    4341           1 :                 add_assoc_long(return_value, "func_overload", MBSTRG(func_overload));
    4342           1 :                 if (MBSTRG(func_overload)){
    4343           1 :                         over_func = &(mb_ovld[0]);
    4344           1 :                         MAKE_STD_ZVAL(row1);
    4345           1 :                         array_init(row1);
    4346          20 :                         while (over_func->type > 0) {
    4347          18 :                                 if ((MBSTRG(func_overload) & over_func->type) == over_func->type ) {
    4348          12 :                                         add_assoc_string(row1, over_func->orig_func, over_func->ovld_func, 1);
    4349             :                                 }
    4350          18 :                                 over_func++;
    4351             :                         }
    4352           1 :                         add_assoc_zval(return_value, "func_overload_list", row1);
    4353             :                 } else {
    4354           0 :                         add_assoc_string(return_value, "func_overload_list", "no overload", 1);
    4355             :                 }
    4356           1 :                 if (lang != NULL) {
    4357           1 :                         if ((name = (char *)mbfl_no_encoding2name(lang->mail_charset)) != NULL) {
    4358           1 :                                 add_assoc_string(return_value, "mail_charset", name, 1);
    4359             :                         }
    4360           1 :                         if ((name = (char *)mbfl_no_encoding2name(lang->mail_header_encoding)) != NULL) {
    4361           1 :                                 add_assoc_string(return_value, "mail_header_encoding", name, 1);
    4362             :                         }
    4363           1 :                         if ((name = (char *)mbfl_no_encoding2name(lang->mail_body_encoding)) != NULL) {
    4364           1 :                                 add_assoc_string(return_value, "mail_body_encoding", name, 1);
    4365             :                         }
    4366             :                 }
    4367           1 :                 add_assoc_long(return_value, "illegal_chars", MBSTRG(illegalchars));
    4368           1 :                 if (MBSTRG(encoding_translation)) {
    4369           1 :                         add_assoc_string(return_value, "encoding_translation", "On", 1);
    4370             :                 } else {
    4371           0 :                         add_assoc_string(return_value, "encoding_translation", "Off", 1);
    4372             :                 }
    4373           1 :                 if ((name = (char *)mbfl_no_language2name(MBSTRG(language))) != NULL) {
    4374           1 :                         add_assoc_string(return_value, "language", name, 1);
    4375             :                 }               
    4376           1 :                 n = MBSTRG(current_detect_order_list_size);
    4377           1 :                 entry = MBSTRG(current_detect_order_list);
    4378           1 :                 if (n > 0) {
    4379             :                         size_t i;
    4380           1 :                         MAKE_STD_ZVAL(row2);
    4381           1 :                         array_init(row2);
    4382           5 :                         for (i = 0; i < n; i++) {
    4383           4 :                                 add_next_index_string(row2, (*entry)->name, 1);
    4384           4 :                                 entry++;
    4385             :                         }
    4386           1 :                         add_assoc_zval(return_value, "detect_order", row2);
    4387             :                 }
    4388           1 :                 if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
    4389           0 :                         add_assoc_string(return_value, "substitute_character", "none", 1);
    4390           1 :                 } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG) {
    4391           0 :                         add_assoc_string(return_value, "substitute_character", "long", 1);
    4392           1 :                 } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY) {
    4393           0 :                         add_assoc_string(return_value, "substitute_character", "entity", 1);
    4394             :                 } else {
    4395           1 :                         add_assoc_long(return_value, "substitute_character", MBSTRG(current_filter_illegal_substchar));
    4396             :                 }
    4397           1 :                 if (MBSTRG(strict_detection)) {
    4398           1 :                         add_assoc_string(return_value, "strict_detection", "On", 1);
    4399             :                 } else {
    4400           0 :                         add_assoc_string(return_value, "strict_detection", "Off", 1);
    4401             :                 }
    4402          15 :         } else if (!strcasecmp("internal_encoding", typ)) {
    4403           1 :                 if (MBSTRG(current_internal_encoding)) {
    4404           1 :                         RETVAL_STRING((char *)MBSTRG(current_internal_encoding)->name, 1);
    4405             :                 }               
    4406          14 :         } else if (!strcasecmp("http_input", typ)) {
    4407           1 :                 if (MBSTRG(http_input_identify)) {
    4408           1 :                         RETVAL_STRING((char *)MBSTRG(http_input_identify)->name, 1);
    4409             :                 }               
    4410          13 :         } else if (!strcasecmp("http_output", typ)) {
    4411           1 :                 if (MBSTRG(current_http_output_encoding)) {
    4412           1 :                         RETVAL_STRING((char *)MBSTRG(current_http_output_encoding)->name, 1);
    4413             :                 }               
    4414          12 :         } else if (!strcasecmp("http_output_conv_mimetypes", typ)) {
    4415           1 :                 if ((name = (char *)zend_ini_string("mbstring.http_output_conv_mimetypes", sizeof("mbstring.http_output_conv_mimetypes"), 0)) != NULL) {
    4416           1 :                         RETVAL_STRING(name, 1);
    4417             :                 }
    4418          11 :         } else if (!strcasecmp("func_overload", typ)) {
    4419           1 :                 RETVAL_LONG(MBSTRG(func_overload));
    4420          10 :         } else if (!strcasecmp("func_overload_list", typ)) {
    4421           1 :                 if (MBSTRG(func_overload)){
    4422           1 :                                 over_func = &(mb_ovld[0]);
    4423           1 :                                 array_init(return_value);
    4424          20 :                                 while (over_func->type > 0) {
    4425          18 :                                         if ((MBSTRG(func_overload) & over_func->type) == over_func->type ) {
    4426          12 :                                                 add_assoc_string(return_value, over_func->orig_func, over_func->ovld_func, 1);
    4427             :                                         }
    4428          18 :                                         over_func++;
    4429             :                                 }
    4430             :                 } else {
    4431           0 :                         RETVAL_STRING("no overload", 1);
    4432             :                 }
    4433           9 :         } else if (!strcasecmp("mail_charset", typ)) {
    4434           1 :                 if (lang != NULL && (name = (char *)mbfl_no_encoding2name(lang->mail_charset)) != NULL) {
    4435           1 :                         RETVAL_STRING(name, 1);
    4436             :                 }
    4437           8 :         } else if (!strcasecmp("mail_header_encoding", typ)) {
    4438           1 :                 if (lang != NULL && (name = (char *)mbfl_no_encoding2name(lang->mail_header_encoding)) != NULL) {
    4439           1 :                         RETVAL_STRING(name, 1);
    4440             :                 }
    4441           7 :         } else if (!strcasecmp("mail_body_encoding", typ)) {
    4442           1 :                 if (lang != NULL && (name = (char *)mbfl_no_encoding2name(lang->mail_body_encoding)) != NULL) {
    4443           1 :                         RETVAL_STRING(name, 1);
    4444             :                 }
    4445           6 :         } else if (!strcasecmp("illegal_chars", typ)) {
    4446           1 :                 RETVAL_LONG(MBSTRG(illegalchars));
    4447           5 :         } else if (!strcasecmp("encoding_translation", typ)) {
    4448           1 :                 if (MBSTRG(encoding_translation)) {
    4449           1 :                         RETVAL_STRING("On", 1);
    4450             :                 } else {
    4451           0 :                         RETVAL_STRING("Off", 1);
    4452             :                 }
    4453           4 :         } else if (!strcasecmp("language", typ)) {
    4454           1 :                 if ((name = (char *)mbfl_no_language2name(MBSTRG(language))) != NULL) {
    4455           1 :                         RETVAL_STRING(name, 1);
    4456             :                 }               
    4457           3 :         } else if (!strcasecmp("detect_order", typ)) {
    4458           1 :                 n = MBSTRG(current_detect_order_list_size);
    4459           1 :                 entry = MBSTRG(current_detect_order_list);
    4460           1 :                 if (n > 0) {
    4461             :                         size_t i;
    4462           1 :                         array_init(return_value);
    4463           5 :                         for (i = 0; i < n; i++) {
    4464           4 :                                 add_next_index_string(return_value, (*entry)->name, 1);
    4465           4 :                                 entry++;
    4466             :                         }
    4467             :                 }
    4468           2 :         } else if (!strcasecmp("substitute_character", typ)) {
    4469           1 :                 if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE) {
    4470           0 :                         RETVAL_STRING("none", 1);
    4471           1 :                 } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_LONG) {
    4472           0 :                         RETVAL_STRING("long", 1);
    4473           1 :                 } else if (MBSTRG(current_filter_illegal_mode) == MBFL_OUTPUTFILTER_ILLEGAL_MODE_ENTITY) {
    4474           0 :                         RETVAL_STRING("entity", 1);
    4475             :                 } else {
    4476           1 :                         RETVAL_LONG(MBSTRG(current_filter_illegal_substchar));
    4477             :                 }
    4478           1 :         } else if (!strcasecmp("strict_detection", typ)) {
    4479           1 :                 if (MBSTRG(strict_detection)) {
    4480           1 :                         RETVAL_STRING("On", 1);
    4481             :                 } else {
    4482           0 :                         RETVAL_STRING("Off", 1);
    4483             :                 }
    4484             :         } else {
    4485           0 :                 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         513 : PHP_FUNCTION(mb_check_encoding)
    4493             : {
    4494         513 :         char *var = NULL;
    4495             :         int var_len;
    4496         513 :         char *enc = NULL;
    4497             :         int enc_len;
    4498             :         mbfl_buffer_converter *convd;
    4499         513 :         const mbfl_encoding *encoding = MBSTRG(current_internal_encoding);
    4500         513 :         mbfl_string string, result, *ret = NULL;
    4501         513 :         long illegalchars = 0;
    4502             : 
    4503         513 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &var, &var_len, &enc, &enc_len) == FAILURE) {
    4504           0 :                 RETURN_FALSE;
    4505             :         }
    4506             : 
    4507         513 :         if (var == NULL) {
    4508           0 :                 RETURN_BOOL(MBSTRG(illegalchars) == 0);
    4509             :         }
    4510             : 
    4511         513 :         if (enc != NULL) {
    4512         513 :                 encoding = mbfl_name2encoding(enc);
    4513         513 :                 if (!encoding || encoding == &mbfl_encoding_pass) {
    4514           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid encoding \"%s\"", enc);
    4515           0 :                         RETURN_FALSE;
    4516             :                 }
    4517             :         }
    4518             : 
    4519         513 :         convd = mbfl_buffer_converter_new2(encoding, encoding, 0);
    4520         513 :         if (convd == NULL) {
    4521           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create converter");
    4522           0 :                 RETURN_FALSE;
    4523             :         }       
    4524         513 :         mbfl_buffer_converter_illegal_mode(convd, MBFL_OUTPUTFILTER_ILLEGAL_MODE_NONE);
    4525         513 :         mbfl_buffer_converter_illegal_substchar(convd, 0);      
    4526             : 
    4527             :         /* initialize string */
    4528         513 :         mbfl_string_init_set(&string, mbfl_no_language_neutral, encoding->no_encoding);
    4529         513 :         mbfl_string_init(&result);
    4530             : 
    4531         513 :         string.val = (unsigned char *)var;
    4532         513 :         string.len = var_len;
    4533         513 :         ret = mbfl_buffer_converter_feed_result(convd, &string, &result);
    4534         513 :         illegalchars = mbfl_buffer_illegalchars(convd);
    4535         513 :         mbfl_buffer_converter_delete(convd);
    4536             : 
    4537         513 :         RETVAL_FALSE;
    4538         513 :         if (ret != NULL) {
    4539         513 :                 if (illegalchars == 0 && string.len == result.len && memcmp(string.val, result.val, string.len) == 0) {
    4540         376 :                         RETVAL_TRUE;
    4541             :                 }
    4542         513 :                 mbfl_string_clear(&result);
    4543             :         }
    4544             : }
    4545             : /* }}} */
    4546             : 
    4547             : 
    4548             : /* {{{ php_mb_populate_current_detect_order_list */
    4549       20182 : static void php_mb_populate_current_detect_order_list(TSRMLS_D)
    4550             : {
    4551       20182 :         const mbfl_encoding **entry = 0;
    4552             :         size_t nentries;
    4553             : 
    4554       20182 :         if (MBSTRG(current_detect_order_list)) {
    4555           0 :                 return;
    4556             :         }
    4557             : 
    4558       20184 :         if (MBSTRG(detect_order_list) && MBSTRG(detect_order_list_size)) {
    4559           2 :                 nentries = MBSTRG(detect_order_list_size);
    4560           2 :                 entry = (const mbfl_encoding **)safe_emalloc(nentries, sizeof(mbfl_encoding*), 0);
    4561           2 :                 memcpy(entry, MBSTRG(detect_order_list), sizeof(mbfl_encoding*) * nentries);
    4562             :         } else {
    4563       20180 :                 const enum mbfl_no_encoding *src = MBSTRG(default_detect_order_list);
    4564             :                 size_t i;
    4565       20180 :                 nentries = MBSTRG(default_detect_order_list_size);
    4566       20180 :                 entry = (const mbfl_encoding **)safe_emalloc(nentries, sizeof(mbfl_encoding*), 0);
    4567       60582 :                 for (i = 0; i < nentries; i++) {
    4568       40402 :                         entry[i] = mbfl_no2encoding(src[i]);
    4569             :                 }
    4570             :         }
    4571       20182 :         MBSTRG(current_detect_order_list) = entry;
    4572       20182 :         MBSTRG(current_detect_order_list_size) = nentries;
    4573             : }
    4574             : 
    4575             : /* {{{ static int php_mb_encoding_translation() */
    4576         211 : static int php_mb_encoding_translation(TSRMLS_D) 
    4577             : {
    4578         211 :         return MBSTRG(encoding_translation);
    4579             : }
    4580             : /* }}} */
    4581             : 
    4582             : /* {{{ MBSTRING_API size_t php_mb_mbchar_bytes_ex() */
    4583        1129 : MBSTRING_API size_t php_mb_mbchar_bytes_ex(const char *s, const mbfl_encoding *enc)
    4584             : {
    4585        1129 :         if (enc != NULL) {
    4586        1129 :                 if (enc->flag & MBFL_ENCTYPE_MBCS) {
    4587        1129 :                         if (enc->mblen_table != NULL) {
    4588        1129 :                                 if (s != NULL) return enc->mblen_table[*(unsigned char *)s];
    4589             :                         }
    4590           0 :                 } else if (enc->flag & (MBFL_ENCTYPE_WCS2BE | MBFL_ENCTYPE_WCS2LE)) {
    4591           0 :                         return 2;
    4592           0 :                 } else if (enc->flag & (MBFL_ENCTYPE_WCS4BE | MBFL_ENCTYPE_WCS4LE)) {
    4593           0 :                         return 4;
    4594             :                 }
    4595             :         }
    4596           0 :         return 1;
    4597             : }
    4598             : /* }}} */
    4599             : 
    4600             : /* {{{ MBSTRING_API size_t php_mb_mbchar_bytes() */
    4601           0 : MBSTRING_API size_t php_mb_mbchar_bytes(const char *s TSRMLS_DC)
    4602             : {
    4603           0 :         return php_mb_mbchar_bytes_ex(s, MBSTRG(internal_encoding));
    4604             : }
    4605             : /* }}} */
    4606             : 
    4607             : /* {{{ MBSTRING_API char *php_mb_safe_strrchr_ex() */
    4608           2 : MBSTRING_API char *php_mb_safe_strrchr_ex(const char *s, unsigned int c, size_t nbytes, const mbfl_encoding *enc)
    4609             : {
    4610           2 :         register const char *p = s;
    4611           2 :         char *last=NULL;
    4612             : 
    4613           2 :         if (nbytes == (size_t)-1) {
    4614           0 :                 size_t nb = 0;
    4615             : 
    4616           0 :                 while (*p != '\0') {
    4617           0 :                         if (nb == 0) {
    4618           0 :                                 if ((unsigned char)*p == (unsigned char)c) {
    4619           0 :                                         last = (char *)p;
    4620             :                                 }
    4621           0 :                                 nb = php_mb_mbchar_bytes_ex(p, enc);
    4622           0 :                                 if (nb == 0) {
    4623           0 :                                         return NULL; /* something is going wrong! */
    4624             :                                 }
    4625             :                         }
    4626           0 :                         --nb;
    4627           0 :                         ++p;
    4628             :                 }
    4629             :         } else {
    4630           2 :                 register size_t bcnt = nbytes;
    4631             :                 register size_t nbytes_char;
    4632          22 :                 while (bcnt > 0) {
    4633          18 :                         if ((unsigned char)*p == (unsigned char)c) {
    4634           0 :                                 last = (char *)p;
    4635             :                         }
    4636          18 :                         nbytes_char = php_mb_mbchar_bytes_ex(p, enc);
    4637          18 :                         if (bcnt < nbytes_char) {
    4638           0 :                                 return NULL;
    4639             :                         }
    4640          18 :                         p += nbytes_char;
    4641          18 :                         bcnt -= nbytes_char;
    4642             :                 }
    4643             :         }
    4644           2 :         return last;
    4645             : }
    4646             : /* }}} */
    4647             : 
    4648             : /* {{{ MBSTRING_API char *php_mb_safe_strrchr() */
    4649           0 : MBSTRING_API char *php_mb_safe_strrchr(const char *s, unsigned int c, size_t nbytes TSRMLS_DC)
    4650             : {
    4651           0 :         return php_mb_safe_strrchr_ex(s, c, nbytes, MBSTRG(internal_encoding));
    4652             : }
    4653             : /* }}} */
    4654             : 
    4655             : /* {{{ MBSTRING_API int php_mb_stripos()
    4656             :  */
    4657         606 : 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         606 :         n = -1;
    4662             : 
    4663         606 :         mbfl_string_init(&haystack);
    4664         606 :         mbfl_string_init(&needle);
    4665         606 :         haystack.no_language = MBSTRG(language);
    4666         606 :         haystack.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    4667         606 :         needle.no_language = MBSTRG(language);
    4668         606 :         needle.no_encoding = MBSTRG(current_internal_encoding)->no_encoding;
    4669             : 
    4670             :         do {
    4671         606 :                 size_t len = 0;
    4672         606 :                 haystack.val = (unsigned char *)php_unicode_convert_case(PHP_UNICODE_CASE_UPPER, (char *)old_haystack, old_haystack_len, &len, from_encoding TSRMLS_CC);
    4673         606 :                 haystack.len = len;
    4674             : 
    4675         606 :                 if (!haystack.val) {
    4676          40 :                         break;
    4677             :                 }
    4678             : 
    4679         566 :                 if (haystack.len <= 0) {
    4680          32 :                         break;
    4681             :                 }
    4682             : 
    4683         534 :                 needle.val = (unsigned char *)php_unicode_convert_case(PHP_UNICODE_CASE_UPPER, (char *)old_needle, old_needle_len, &len, from_encoding TSRMLS_CC);
    4684         534 :                 needle.len = len;
    4685             : 
    4686         534 :                 if (!needle.val) {
    4687           0 :                         break;
    4688             :                 }
    4689             : 
    4690         534 :                 if (needle.len <= 0) {
    4691          16 :                         break;
    4692             :                 }
    4693             : 
    4694         518 :                 haystack.no_encoding = needle.no_encoding = mbfl_name2no_encoding(from_encoding);
    4695         518 :                 if (haystack.no_encoding == mbfl_no_encoding_invalid) {
    4696           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown encoding \"%s\"", from_encoding);
    4697           0 :                         break;
    4698             :                 }
    4699             : 
    4700             :                 {
    4701         518 :                         int haystack_char_len = mbfl_strlen(&haystack);
    4702             :  
    4703         518 :                         if (mode) {
    4704         250 :                                 if ((offset > 0 && offset > haystack_char_len) ||
    4705           7 :                                         (offset < 0 && -offset > haystack_char_len)) {
    4706          14 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset is greater than the length of haystack string");
    4707          14 :                                         break;
    4708             :                                 }
    4709             :                         } else {
    4710         275 :                                 if (offset < 0 || offset > haystack_char_len) {
    4711          26 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset not contained in string");
    4712          26 :                                         break;
    4713             :                                 }
    4714             :                         }
    4715             :                 }
    4716             : 
    4717         478 :                 n = mbfl_strpos(&haystack, &needle, offset, mode);
    4718             :         } while(0);
    4719             : 
    4720         606 :         if (haystack.val) {
    4721         566 :                 efree(haystack.val);
    4722             :         }
    4723             : 
    4724         606 :         if (needle.val) {
    4725         534 :                 efree(needle.val);
    4726             :         }
    4727             : 
    4728         606 :         return n;
    4729             : }
    4730             : /* }}} */
    4731             : 
    4732           1 : static void php_mb_gpc_get_detect_order(const zend_encoding ***list, size_t *list_size TSRMLS_DC) /* {{{ */
    4733             : {
    4734           1 :         *list = (const zend_encoding **)MBSTRG(http_input_list);
    4735           1 :         *list_size = MBSTRG(http_input_list_size);
    4736           1 : }
    4737             : /* }}} */
    4738             : 
    4739           0 : static void php_mb_gpc_set_input_encoding(const zend_encoding *encoding TSRMLS_DC) /* {{{ */
    4740             : {
    4741           0 :         MBSTRG(http_input_identify) = (const mbfl_encoding*)encoding;
    4742           0 : }
    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             :  */

Generated by: LCOV version 1.10

Generated at Sun, 21 Sep 2014 15:27:37 +0000 (10 hours ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.