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

LTP GCOV extension - code coverage report
Current view: directory - mbstring - mbstring.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 2055
Code covered: 64.3 % Executed lines: 1321
Legend: not executed executed

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