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-19 Instrumented lines: 2092
Code covered: 63.0 % Executed lines: 1317
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:10 +0000 (5 days ago)

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