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

Generated by: LCOV version 1.10

Generated at Wed, 16 Apr 2014 12:47:50 +0000 (26 hours ago)

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