LTP GCOV extension - code coverage report
Current view: directory - ext/standard - string.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 2380
Code covered: 18.2 % Executed lines: 433
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2007 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                 :    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
      16                 :    |          Stig Sæther Bakken <ssb@php.net>                            |
      17                 :    |          Zeev Suraski <zeev@zend.com>                                |
      18                 :    +----------------------------------------------------------------------+
      19                 :  */
      20                 : 
      21                 : /* $Id: string.c,v 1.445.2.14.2.54 2007/03/26 10:25:41 tony2001 Exp $ */
      22                 : 
      23                 : /* Synced with php 3.0 revision 1.193 1999-06-16 [ssb] */
      24                 : 
      25                 : #include <stdio.h>
      26                 : #include "php.h"
      27                 : #include "reg.h"
      28                 : #include "php_rand.h"
      29                 : #include "php_string.h"
      30                 : #include "php_variables.h"
      31                 : #ifdef HAVE_LOCALE_H
      32                 : # include <locale.h>
      33                 : #endif
      34                 : #ifdef HAVE_LANGINFO_H
      35                 : # include <langinfo.h>
      36                 : #endif
      37                 : #ifdef HAVE_MONETARY_H
      38                 : # include <monetary.h>
      39                 : #endif
      40                 : #ifdef HAVE_LIBINTL
      41                 : # include <libintl.h> /* For LC_MESSAGES */
      42                 : #endif
      43                 : 
      44                 : #include <math.h>
      45                 : 
      46                 : #include "scanf.h"
      47                 : #include "zend_API.h"
      48                 : #include "zend_execute.h"
      49                 : #include "php_globals.h"
      50                 : #include "basic_functions.h"
      51                 : #include "php_smart_str.h"
      52                 : #ifdef ZTS
      53                 : #include "TSRM.h"
      54                 : #endif
      55                 : 
      56                 : #define STR_PAD_LEFT                    0
      57                 : #define STR_PAD_RIGHT                   1
      58                 : #define STR_PAD_BOTH                    2
      59                 : #define PHP_PATHINFO_DIRNAME    1
      60                 : #define PHP_PATHINFO_BASENAME   2
      61                 : #define PHP_PATHINFO_EXTENSION  4
      62                 : #define PHP_PATHINFO_FILENAME   8
      63                 : #define PHP_PATHINFO_ALL        (PHP_PATHINFO_DIRNAME | PHP_PATHINFO_BASENAME | PHP_PATHINFO_EXTENSION | PHP_PATHINFO_FILENAME)
      64                 : 
      65                 : #define STR_STRSPN                              0
      66                 : #define STR_STRCSPN                             1
      67                 : 
      68                 : /* {{{ register_string_constants
      69                 :  */
      70                 : void register_string_constants(INIT_FUNC_ARGS)
      71             220 : {
      72             220 :         REGISTER_LONG_CONSTANT("STR_PAD_LEFT", STR_PAD_LEFT, CONST_CS | CONST_PERSISTENT);
      73             220 :         REGISTER_LONG_CONSTANT("STR_PAD_RIGHT", STR_PAD_RIGHT, CONST_CS | CONST_PERSISTENT);
      74             220 :         REGISTER_LONG_CONSTANT("STR_PAD_BOTH", STR_PAD_BOTH, CONST_CS | CONST_PERSISTENT);
      75             220 :         REGISTER_LONG_CONSTANT("PATHINFO_DIRNAME", PHP_PATHINFO_DIRNAME, CONST_CS | CONST_PERSISTENT);
      76             220 :         REGISTER_LONG_CONSTANT("PATHINFO_BASENAME", PHP_PATHINFO_BASENAME, CONST_CS | CONST_PERSISTENT);
      77             220 :         REGISTER_LONG_CONSTANT("PATHINFO_EXTENSION", PHP_PATHINFO_EXTENSION, CONST_CS | CONST_PERSISTENT);
      78             220 :         REGISTER_LONG_CONSTANT("PATHINFO_FILENAME", PHP_PATHINFO_FILENAME, CONST_CS | CONST_PERSISTENT);
      79                 : 
      80                 : #ifdef HAVE_LOCALECONV
      81                 :         /* If last members of struct lconv equal CHAR_MAX, no grouping is done */       
      82                 : 
      83                 : /* This is bad, but since we are going to be hardcoding in the POSIX stuff anyway... */
      84                 : # ifndef HAVE_LIMITS_H
      85                 : # define CHAR_MAX 127
      86                 : # endif
      87                 : 
      88             220 :         REGISTER_LONG_CONSTANT("CHAR_MAX", CHAR_MAX, CONST_CS | CONST_PERSISTENT);
      89                 : #endif
      90                 : 
      91                 : #ifdef HAVE_LOCALE_H
      92             220 :         REGISTER_LONG_CONSTANT("LC_CTYPE", LC_CTYPE, CONST_CS | CONST_PERSISTENT);
      93             220 :         REGISTER_LONG_CONSTANT("LC_NUMERIC", LC_NUMERIC, CONST_CS | CONST_PERSISTENT);
      94             220 :         REGISTER_LONG_CONSTANT("LC_TIME", LC_TIME, CONST_CS | CONST_PERSISTENT);
      95             220 :         REGISTER_LONG_CONSTANT("LC_COLLATE", LC_COLLATE, CONST_CS | CONST_PERSISTENT);
      96             220 :         REGISTER_LONG_CONSTANT("LC_MONETARY", LC_MONETARY, CONST_CS | CONST_PERSISTENT);
      97             220 :         REGISTER_LONG_CONSTANT("LC_ALL", LC_ALL, CONST_CS | CONST_PERSISTENT);
      98                 : # ifdef LC_MESSAGES
      99             220 :         REGISTER_LONG_CONSTANT("LC_MESSAGES", LC_MESSAGES, CONST_CS | CONST_PERSISTENT);
     100                 : # endif
     101                 : #endif
     102                 :         
     103             220 : }
     104                 : /* }}} */
     105                 : 
     106                 : int php_tag_find(char *tag, int len, char *set);
     107                 : 
     108                 : /* this is read-only, so it's ok */
     109                 : static char hexconvtab[] = "0123456789abcdef";
     110                 : 
     111                 : /* localeconv mutex */
     112                 : #ifdef ZTS
     113                 : static MUTEX_T locale_mutex = NULL;
     114                 : #endif
     115                 : 
     116                 : /* {{{ php_bin2hex
     117                 :  */
     118                 : static char *php_bin2hex(const unsigned char *old, const size_t oldlen, size_t *newlen)
     119               0 : {
     120               0 :         register unsigned char *result = NULL;
     121                 :         size_t i, j;
     122                 : 
     123               0 :         result = (char *) safe_emalloc(oldlen * 2, sizeof(char), 1);
     124                 :         
     125               0 :         for (i = j = 0; i < oldlen; i++) {
     126               0 :                 result[j++] = hexconvtab[old[i] >> 4];
     127               0 :                 result[j++] = hexconvtab[old[i] & 15];
     128                 :         }
     129               0 :         result[j] = '\0';
     130                 : 
     131               0 :         if (newlen) 
     132               0 :                 *newlen = oldlen * 2 * sizeof(char);
     133                 : 
     134               0 :         return result;
     135                 : }
     136                 : /* }}} */
     137                 : 
     138                 : #ifdef HAVE_LOCALECONV
     139                 : /* {{{ localeconv_r
     140                 :  * glibc's localeconv is not reentrant, so lets make it so ... sorta */
     141                 : PHPAPI struct lconv *localeconv_r(struct lconv *out)
     142               0 : {
     143                 :         struct lconv *res;
     144                 : 
     145                 : # ifdef ZTS
     146                 :         tsrm_mutex_lock( locale_mutex );
     147                 : # endif
     148                 : 
     149                 :         /* localeconv doesn't return an error condition */
     150               0 :         res = localeconv();
     151                 : 
     152               0 :         *out = *res;
     153                 : 
     154                 : # ifdef ZTS
     155                 :         tsrm_mutex_unlock( locale_mutex );
     156                 : # endif
     157                 : 
     158               0 :         return out;
     159                 : }
     160                 : /* }}} */
     161                 : 
     162                 : # ifdef ZTS
     163                 : /* {{{ PHP_MINIT_FUNCTION
     164                 :  */
     165                 : PHP_MINIT_FUNCTION(localeconv)
     166                 : {
     167                 :         locale_mutex = tsrm_mutex_alloc();
     168                 :         return SUCCESS;
     169                 : }
     170                 : /* }}} */
     171                 : 
     172                 : /* {{{ PHP_MSHUTDOWN_FUNCTION
     173                 :  */
     174                 : PHP_MSHUTDOWN_FUNCTION(localeconv)
     175                 : {
     176                 :         tsrm_mutex_free( locale_mutex );
     177                 :         locale_mutex = NULL;
     178                 :         return SUCCESS;
     179                 : }
     180                 : /* }}} */
     181                 : # endif
     182                 : #endif
     183                 : 
     184                 : /* {{{ proto string bin2hex(string data)
     185                 :    Converts the binary representation of data to hex */
     186                 : PHP_FUNCTION(bin2hex)
     187               0 : {
     188                 :         zval **data;
     189                 :         char *result;
     190                 :         size_t newlen;
     191                 : 
     192               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &data) == FAILURE) {
     193               0 :                 WRONG_PARAM_COUNT;
     194                 :         }
     195               0 :         convert_to_string_ex(data);
     196                 : 
     197               0 :         result = php_bin2hex(Z_STRVAL_PP(data), Z_STRLEN_PP(data), &newlen);
     198                 :         
     199               0 :         if (!result) {
     200               0 :                 RETURN_FALSE;
     201                 :         }
     202                 : 
     203               0 :         RETURN_STRINGL(result, newlen, 0);
     204                 : }
     205                 : /* }}} */
     206                 : 
     207                 : static void php_spn_common_handler(INTERNAL_FUNCTION_PARAMETERS, int behavior)
     208               0 : {
     209                 :         char *s11, *s22;
     210                 :         int len1, len2;
     211                 :         long start, len;
     212                 :         
     213               0 :         start = 0;
     214               0 :         len = 0;
     215               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|ll", &s11, &len1,
     216                 :                                 &s22, &len2, &start, &len) == FAILURE) {
     217               0 :                 return;
     218                 :         }
     219                 :         
     220               0 :         if (ZEND_NUM_ARGS() < 4) {
     221               0 :                 len = len1;
     222                 :         }
     223                 :         
     224                 :         /* look at substr() function for more information */
     225                 :         
     226               0 :         if (start < 0) {
     227               0 :                 start += len1;
     228               0 :                 if (start < 0) {
     229               0 :                         start = 0;
     230                 :                 }
     231               0 :         } else if (start > len1) {
     232               0 :                 RETURN_FALSE;
     233                 :         }
     234                 :         
     235               0 :         if (len < 0) {
     236               0 :                 len += (len1 - start);
     237               0 :                 if (len < 0) {
     238               0 :                         len = 0;
     239                 :                 }
     240                 :         }
     241                 :         
     242               0 :         if ((start + len) > len1) {
     243               0 :                 len = len1 - start;
     244                 :         }
     245                 : 
     246               0 :         if (behavior == STR_STRSPN) {
     247               0 :                 RETURN_LONG(php_strspn(s11 + start /*str1_start*/,
     248                 :                                                 s22 /*str2_start*/,
     249                 :                                                 s11 + start + len /*str1_end*/,
     250                 :                                                 s22 + len2 /*str2_end*/));
     251               0 :         } else if (behavior == STR_STRCSPN) {
     252               0 :                 RETURN_LONG(php_strcspn(s11 + start /*str1_start*/,
     253                 :                                                 s22 /*str2_start*/,
     254                 :                                                 s11 + start + len /*str1_end*/,
     255                 :                                                 s22 + len2 /*str2_end*/));
     256                 :         }
     257                 :         
     258                 : }
     259                 : 
     260                 : /* {{{ proto int strspn(string str, string mask [, start [, len]])
     261                 :    Finds length of initial segment consisting entirely of characters found in mask. If start or/and length is provided works like strspn(substr($s,$start,$len),$good_chars) */
     262                 : PHP_FUNCTION(strspn)
     263               0 : {
     264               0 :         php_spn_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, STR_STRSPN);
     265               0 : }
     266                 : /* }}} */
     267                 : 
     268                 : /* {{{ proto int strcspn(string str, string mask [, start [, len]])
     269                 :    Finds length of initial segment consisting entirely of characters not found in mask. If start or/and length is provide works like strcspn(substr($s,$start,$len),$bad_chars) */
     270                 : PHP_FUNCTION(strcspn)
     271               0 : {
     272               0 :         php_spn_common_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU, STR_STRCSPN);
     273               0 : }
     274                 : /* }}} */
     275                 : 
     276                 : /* {{{ PHP_MINIT_FUNCTION(nl_langinfo) */
     277                 : #if HAVE_NL_LANGINFO
     278                 : PHP_MINIT_FUNCTION(nl_langinfo)
     279             220 : {
     280                 : #define REGISTER_NL_LANGINFO_CONSTANT(x)        REGISTER_LONG_CONSTANT(#x, x, CONST_CS | CONST_PERSISTENT)
     281                 : #ifdef ABDAY_1
     282             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_1);
     283             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_2);
     284             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_3);
     285             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_4);
     286             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_5);
     287             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_6);
     288             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABDAY_7);
     289                 : #endif
     290                 : #ifdef DAY_1
     291             220 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_1);
     292             220 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_2);
     293             220 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_3);
     294             220 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_4);
     295             220 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_5);
     296             220 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_6);
     297             220 :         REGISTER_NL_LANGINFO_CONSTANT(DAY_7);
     298                 : #endif
     299                 : #ifdef ABMON_1
     300             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_1);
     301             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_2);
     302             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_3);
     303             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_4);
     304             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_5);
     305             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_6);
     306             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_7);
     307             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_8);
     308             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_9);
     309             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_10);
     310             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_11);
     311             220 :         REGISTER_NL_LANGINFO_CONSTANT(ABMON_12);
     312                 : #endif
     313                 : #ifdef MON_1
     314             220 :         REGISTER_NL_LANGINFO_CONSTANT(MON_1);
     315             220 :         REGISTER_NL_LANGINFO_CONSTANT(MON_2);
     316             220 :         REGISTER_NL_LANGINFO_CONSTANT(MON_3);
     317             220 :         REGISTER_NL_LANGINFO_CONSTANT(MON_4);
     318             220 :         REGISTER_NL_LANGINFO_CONSTANT(MON_5);
     319             220 :         REGISTER_NL_LANGINFO_CONSTANT(MON_6);
     320             220 :         REGISTER_NL_LANGINFO_CONSTANT(MON_7);
     321             220 :         REGISTER_NL_LANGINFO_CONSTANT(MON_8);
     322             220 :         REGISTER_NL_LANGINFO_CONSTANT(MON_9);
     323             220 :         REGISTER_NL_LANGINFO_CONSTANT(MON_10);
     324             220 :         REGISTER_NL_LANGINFO_CONSTANT(MON_11);
     325             220 :         REGISTER_NL_LANGINFO_CONSTANT(MON_12);
     326                 : #endif
     327                 : #ifdef AM_STR
     328             220 :         REGISTER_NL_LANGINFO_CONSTANT(AM_STR);
     329                 : #endif
     330                 : #ifdef PM_STR
     331             220 :         REGISTER_NL_LANGINFO_CONSTANT(PM_STR);
     332                 : #endif
     333                 : #ifdef D_T_FMT
     334             220 :         REGISTER_NL_LANGINFO_CONSTANT(D_T_FMT);
     335                 : #endif
     336                 : #ifdef D_FMT
     337             220 :         REGISTER_NL_LANGINFO_CONSTANT(D_FMT);
     338                 : #endif
     339                 : #ifdef T_FMT
     340             220 :         REGISTER_NL_LANGINFO_CONSTANT(T_FMT);
     341                 : #endif
     342                 : #ifdef T_FMT_AMPM
     343             220 :         REGISTER_NL_LANGINFO_CONSTANT(T_FMT_AMPM);
     344                 : #endif
     345                 : #ifdef ERA
     346             220 :         REGISTER_NL_LANGINFO_CONSTANT(ERA);
     347                 : #endif
     348                 : #ifdef ERA_YEAR
     349                 :         REGISTER_NL_LANGINFO_CONSTANT(ERA_YEAR);
     350                 : #endif
     351                 : #ifdef ERA_D_T_FMT
     352             220 :         REGISTER_NL_LANGINFO_CONSTANT(ERA_D_T_FMT);
     353                 : #endif
     354                 : #ifdef ERA_D_FMT
     355             220 :         REGISTER_NL_LANGINFO_CONSTANT(ERA_D_FMT);
     356                 : #endif
     357                 : #ifdef ERA_T_FMT
     358             220 :         REGISTER_NL_LANGINFO_CONSTANT(ERA_T_FMT);
     359                 : #endif
     360                 : #ifdef ALT_DIGITS
     361             220 :         REGISTER_NL_LANGINFO_CONSTANT(ALT_DIGITS);
     362                 : #endif
     363                 : #ifdef INT_CURR_SYMBOL
     364                 :         REGISTER_NL_LANGINFO_CONSTANT(INT_CURR_SYMBOL);
     365                 : #endif
     366                 : #ifdef CURRENCY_SYMBOL
     367                 :         REGISTER_NL_LANGINFO_CONSTANT(CURRENCY_SYMBOL);
     368                 : #endif
     369                 : #ifdef CRNCYSTR
     370             220 :         REGISTER_NL_LANGINFO_CONSTANT(CRNCYSTR);
     371                 : #endif
     372                 : #ifdef MON_DECIMAL_POINT
     373                 :         REGISTER_NL_LANGINFO_CONSTANT(MON_DECIMAL_POINT);
     374                 : #endif
     375                 : #ifdef MON_THOUSANDS_SEP
     376                 :         REGISTER_NL_LANGINFO_CONSTANT(MON_THOUSANDS_SEP);
     377                 : #endif
     378                 : #ifdef MON_GROUPING
     379                 :         REGISTER_NL_LANGINFO_CONSTANT(MON_GROUPING);
     380                 : #endif
     381                 : #ifdef POSITIVE_SIGN
     382                 :         REGISTER_NL_LANGINFO_CONSTANT(POSITIVE_SIGN);
     383                 : #endif
     384                 : #ifdef NEGATIVE_SIGN
     385                 :         REGISTER_NL_LANGINFO_CONSTANT(NEGATIVE_SIGN);
     386                 : #endif
     387                 : #ifdef INT_FRAC_DIGITS
     388                 :         REGISTER_NL_LANGINFO_CONSTANT(INT_FRAC_DIGITS);
     389                 : #endif
     390                 : #ifdef FRAC_DIGITS
     391                 :         REGISTER_NL_LANGINFO_CONSTANT(FRAC_DIGITS);
     392                 : #endif
     393                 : #ifdef P_CS_PRECEDES
     394                 :         REGISTER_NL_LANGINFO_CONSTANT(P_CS_PRECEDES);
     395                 : #endif
     396                 : #ifdef P_SEP_BY_SPACE
     397                 :         REGISTER_NL_LANGINFO_CONSTANT(P_SEP_BY_SPACE);
     398                 : #endif
     399                 : #ifdef N_CS_PRECEDES
     400                 :         REGISTER_NL_LANGINFO_CONSTANT(N_CS_PRECEDES);
     401                 : #endif
     402                 : #ifdef N_SEP_BY_SPACE
     403                 :         REGISTER_NL_LANGINFO_CONSTANT(N_SEP_BY_SPACE);
     404                 : #endif
     405                 : #ifdef P_SIGN_POSN
     406                 :         REGISTER_NL_LANGINFO_CONSTANT(P_SIGN_POSN);
     407                 : #endif
     408                 : #ifdef N_SIGN_POSN
     409                 :         REGISTER_NL_LANGINFO_CONSTANT(N_SIGN_POSN);
     410                 : #endif
     411                 : #ifdef DECIMAL_POINT
     412                 :         REGISTER_NL_LANGINFO_CONSTANT(DECIMAL_POINT);
     413                 : #endif
     414                 : #ifdef RADIXCHAR
     415             220 :         REGISTER_NL_LANGINFO_CONSTANT(RADIXCHAR);
     416                 : #endif
     417                 : #ifdef THOUSANDS_SEP
     418                 :         REGISTER_NL_LANGINFO_CONSTANT(THOUSANDS_SEP);
     419                 : #endif
     420                 : #ifdef THOUSEP
     421             220 :         REGISTER_NL_LANGINFO_CONSTANT(THOUSEP);
     422                 : #endif
     423                 : #ifdef GROUPING
     424                 :         REGISTER_NL_LANGINFO_CONSTANT(GROUPING);
     425                 : #endif
     426                 : #ifdef YESEXPR
     427             220 :         REGISTER_NL_LANGINFO_CONSTANT(YESEXPR);
     428                 : #endif
     429                 : #ifdef NOEXPR
     430             220 :         REGISTER_NL_LANGINFO_CONSTANT(NOEXPR);
     431                 : #endif
     432                 : #ifdef YESSTR
     433                 :         REGISTER_NL_LANGINFO_CONSTANT(YESSTR);
     434                 : #endif
     435                 : #ifdef NOSTR
     436                 :         REGISTER_NL_LANGINFO_CONSTANT(NOSTR);
     437                 : #endif
     438                 : #ifdef CODESET
     439             220 :         REGISTER_NL_LANGINFO_CONSTANT(CODESET);
     440                 : #endif
     441                 : #undef REGISTER_NL_LANGINFO_CONSTANT
     442             220 :         return SUCCESS;
     443                 : }
     444                 : /* }}} */
     445                 : 
     446                 : /* {{{ proto string nl_langinfo(int item)
     447                 :    Query language and locale information */
     448                 : PHP_FUNCTION(nl_langinfo)
     449               0 : {
     450                 :         zval **item;
     451                 :         char *value;
     452                 :         
     453               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &item) == FAILURE) {
     454               0 :                 WRONG_PARAM_COUNT;
     455                 :         }
     456               0 :         convert_to_long_ex(item);
     457                 : 
     458               0 :         value = nl_langinfo(Z_LVAL_PP(item));
     459               0 :         if (value == NULL) {
     460               0 :                 RETURN_FALSE;
     461                 :         } else {
     462               0 :                 RETURN_STRING(value, 1);
     463                 :         }
     464                 : }
     465                 : #endif
     466                 : /* }}} */
     467                 : 
     468                 : #ifdef HAVE_STRCOLL
     469                 : /* {{{ proto int strcoll(string str1, string str2)
     470                 :    Compares two strings using the current locale */
     471                 : PHP_FUNCTION(strcoll)
     472               0 : {
     473                 :         zval **s1, **s2;
     474                 : 
     475               0 :         if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &s1, &s2) == FAILURE) {
     476               0 :                 WRONG_PARAM_COUNT;
     477                 :         }
     478               0 :         convert_to_string_ex(s1);
     479               0 :         convert_to_string_ex(s2);
     480                 : 
     481               0 :         RETURN_LONG(strcoll((const char *) Z_STRVAL_PP(s1), 
     482                 :                             (const char *) Z_STRVAL_PP(s2)));
     483                 : }
     484                 : /* }}} */
     485                 : #endif
     486                 : 
     487                 : /* {{{ php_charmask
     488                 :  * Fills a 256-byte bytemask with input. You can specify a range like 'a..z',
     489                 :  * it needs to be incrementing.  
     490                 :  * Returns: FAILURE/SUCCESS whether the input was correct (i.e. no range errors)
     491                 :  */
     492                 : static inline int php_charmask(unsigned char *input, int len, char *mask TSRMLS_DC)
     493            5496 : {
     494                 :         unsigned char *end;
     495                 :         unsigned char c;
     496            5496 :         int result = SUCCESS;
     497                 : 
     498            5496 :         memset(mask, 0, 256);
     499           38472 :         for (end = input+len; input < end; input++) {
     500           32976 :                 c=*input; 
     501           32976 :                 if ((input+3 < end) && input[1] == '.' && input[2] == '.' 
     502                 :                                 && input[3] >= c) {
     503               0 :                         memset(mask+c, 1, input[3] - c + 1);
     504               0 :                         input+=3;
     505           32976 :                 } else if ((input+1 < end) && input[0] == '.' && input[1] == '.') {
     506                 :                         /* Error, try to be as helpful as possible:
     507                 :                            (a range ending/starting with '.' won't be captured here) */
     508               0 :                         if (end-len >= input) { /* there was no 'left' char */
     509               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid '..'-range, no character to the left of '..'.");
     510               0 :                                 result = FAILURE;
     511               0 :                                 continue;
     512                 :                         }
     513               0 :                         if (input+2 >= end) { /* there is no 'right' char */
     514               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid '..'-range, no character to the right of '..'.");
     515               0 :                                 result = FAILURE;
     516               0 :                                 continue;
     517                 :                         }
     518               0 :                         if (input[-1] > input[2]) { /* wrong order */
     519               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid '..'-range, '..'-range needs to be incrementing.");
     520               0 :                                 result = FAILURE;
     521               0 :                                 continue;
     522                 :                         } 
     523                 :                         /* FIXME: better error (a..b..c is the only left possibility?) */
     524               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid '..'-range.");
     525               0 :                         result = FAILURE;
     526               0 :                         continue;
     527                 :                 } else {
     528           32976 :                         mask[c]=1;
     529                 :                 }
     530                 :         }
     531            5496 :         return result;
     532                 : }
     533                 : /* }}} */
     534                 : 
     535                 : /* {{{ php_trim()
     536                 :  * mode 1 : trim left
     537                 :  * mode 2 : trim right
     538                 :  * mode 3 : trim left and right
     539                 :  * what indicates which chars are to be trimmed. NULL->default (' \t\n\r\v\0')
     540                 :  */
     541                 : PHPAPI char *php_trim(char *c, int len, char *what, int what_len, zval *return_value, int mode TSRMLS_DC)
     542            5496 : {
     543                 :         register int i;
     544            5496 :         int trimmed = 0;
     545                 :         char mask[256];
     546                 : 
     547            5496 :         if (what) {
     548               0 :                 php_charmask(what, what_len, mask TSRMLS_CC);
     549                 :         } else {
     550            5496 :                 php_charmask(" \n\r\t\v\0", 6, mask TSRMLS_CC);
     551                 :         }
     552                 : 
     553            5496 :         if (mode & 1) {
     554            5496 :                 for (i = 0; i < len; i++) {
     555            4078 :                         if (mask[(unsigned char)c[i]]) {
     556               0 :                                 trimmed++;
     557                 :                         } else {
     558            4078 :                                 break;
     559                 :                         }
     560                 :                 }
     561            5496 :                 len -= trimmed;
     562            5496 :                 c += trimmed;
     563                 :         }
     564            5496 :         if (mode & 2) {
     565            5773 :                 for (i = len - 1; i >= 0; i--) {
     566            4676 :                         if (mask[(unsigned char)c[i]]) {
     567             599 :                                 len--;
     568                 :                         } else {
     569            4077 :                                 break;
     570                 :                         }
     571                 :                 }
     572                 :         }
     573                 : 
     574            5496 :         if (return_value) {
     575            5496 :                 RETVAL_STRINGL(c, len, 1);
     576                 :         } else {
     577               0 :                 return estrndup(c, len);
     578                 :         }
     579            5496 :         return "";
     580                 : }
     581                 : /* }}} */
     582                 : 
     583                 : /* {{{ php_do_trim
     584                 :  * Base for trim(), rtrim() and ltrim() functions.
     585                 :  */
     586                 : static void php_do_trim(INTERNAL_FUNCTION_PARAMETERS, int mode)
     587            5496 : {
     588                 :         zval **str;
     589            5496 :         zval **what = NULL;
     590            5496 :         int    argc = ZEND_NUM_ARGS();
     591                 : 
     592            5496 :         if (argc < 1 || argc > 2 || zend_get_parameters_ex(argc, &str, &what) == FAILURE) {
     593               0 :                 WRONG_PARAM_COUNT;
     594                 :         }
     595                 : 
     596            5496 :         convert_to_string_ex(str);
     597                 : 
     598            5496 :         if (argc > 1) {
     599               0 :                 convert_to_string_ex(what);
     600               0 :                 php_trim(Z_STRVAL_PP(str), Z_STRLEN_PP(str), Z_STRVAL_PP(what), Z_STRLEN_PP(what), return_value, mode TSRMLS_CC);
     601                 :         } else {
     602            5496 :                 php_trim(Z_STRVAL_PP(str), Z_STRLEN_PP(str), NULL, 0, return_value, mode TSRMLS_CC);
     603                 :         }
     604                 : }
     605                 : /* }}} */
     606                 : 
     607                 : /* {{{ proto string trim(string str [, string character_mask])
     608                 :    Strips whitespace from the beginning and end of a string */
     609                 : PHP_FUNCTION(trim)
     610            5174 : {
     611            5174 :         php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 3);
     612            5174 : }
     613                 : /* }}} */
     614                 : 
     615                 : /* {{{ proto string rtrim(string str [, string character_mask])
     616                 :    Removes trailing whitespace */
     617                 : PHP_FUNCTION(rtrim)
     618               0 : {
     619               0 :         php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 2);
     620               0 : }
     621                 : /* }}} */
     622                 : 
     623                 : /* {{{ proto string ltrim(string str [, string character_mask])
     624                 :    Strips whitespace from the beginning of a string */
     625                 : PHP_FUNCTION(ltrim)
     626             322 : {
     627             322 :         php_do_trim(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     628             322 : }
     629                 : /* }}} */
     630                 : 
     631                 : /* {{{ proto string wordwrap(string str [, int width [, string break [, boolean cut]]])
     632                 :    Wraps buffer to selected number of characters using string break char */
     633                 : PHP_FUNCTION(wordwrap)
     634               0 : {
     635               0 :         const char *text, *breakchar = "\n";
     636                 :         char *newtext;
     637               0 :         int textlen, breakcharlen = 1, newtextlen, chk;
     638                 :         size_t alloced;
     639               0 :         long current = 0, laststart = 0, lastspace = 0;
     640               0 :         long linelength = 75;
     641               0 :         zend_bool docut = 0;
     642                 : 
     643               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lsb", &text, &textlen, &linelength, &breakchar, &breakcharlen, &docut) == FAILURE) {
     644               0 :                 return;
     645                 :         }
     646                 : 
     647               0 :         if (textlen == 0) {
     648               0 :                 RETURN_EMPTY_STRING();
     649                 :         }
     650                 : 
     651               0 :         if (linelength == 0 && docut) {
     652               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't force cut when width is zero.");
     653               0 :                 RETURN_FALSE;
     654                 :         }
     655                 : 
     656                 :         /* Special case for a single-character break as it needs no
     657                 :            additional storage space */
     658               0 :         if (breakcharlen == 1 && !docut) {
     659               0 :                 newtext = estrndup(text, textlen);
     660                 : 
     661               0 :                 laststart = lastspace = 0;
     662               0 :                 for (current = 0; current < textlen; current++) {
     663               0 :                         if (text[current] == breakchar[0]) {
     664               0 :                                 laststart = lastspace = current;
     665               0 :                         } else if (text[current] == ' ') {
     666               0 :                                 if (current - laststart >= linelength) {
     667               0 :                                         newtext[current] = breakchar[0];
     668               0 :                                         laststart = current + 1;
     669                 :                                 }
     670               0 :                                 lastspace = current;
     671               0 :                         } else if (current - laststart >= linelength && laststart != lastspace) {
     672               0 :                                 newtext[lastspace] = breakchar[0];
     673               0 :                                 laststart = lastspace + 1;
     674                 :                         }
     675                 :                 }
     676                 : 
     677               0 :                 RETURN_STRINGL(newtext, textlen, 0);
     678                 :         } else {
     679                 :                 /* Multiple character line break or forced cut */
     680               0 :                 if (linelength > 0) {
     681               0 :                         chk = (int)(textlen/linelength + 1);
     682               0 :                         newtext = safe_emalloc(chk, breakcharlen, textlen + 1);
     683               0 :                         alloced = textlen + chk * breakcharlen + 1;
     684                 :                 } else {
     685               0 :                         chk = textlen;
     686               0 :                         alloced = textlen * (breakcharlen + 1) + 1;
     687               0 :                         newtext = safe_emalloc(textlen, (breakcharlen + 1), 1);
     688                 :                 }
     689                 : 
     690                 :                 /* now keep track of the actual new text length */
     691               0 :                 newtextlen = 0;
     692                 : 
     693               0 :                 laststart = lastspace = 0;
     694               0 :                 for (current = 0; current < textlen; current++) {
     695               0 :                         if (chk <= 0) {
     696               0 :                                 alloced += (int) (((textlen - current + 1)/linelength + 1) * breakcharlen) + 1;
     697               0 :                                 newtext = erealloc(newtext, alloced);
     698               0 :                                 chk = (int) ((textlen - current)/linelength) + 1;
     699                 :                         }
     700                 :                         /* when we hit an existing break, copy to new buffer, and
     701                 :                          * fix up laststart and lastspace */
     702               0 :                         if (text[current] == breakchar[0]
     703                 :                                 && current + breakcharlen < textlen
     704                 :                                 && !strncmp(text+current, breakchar, breakcharlen)) {
     705               0 :                                 memcpy(newtext+newtextlen, text+laststart, current-laststart+breakcharlen);
     706               0 :                                 newtextlen += current-laststart+breakcharlen;
     707               0 :                                 current += breakcharlen - 1;
     708               0 :                                 laststart = lastspace = current + 1;
     709               0 :                                 chk--;
     710                 :                         }
     711                 :                         /* if it is a space, check if it is at the line boundary,
     712                 :                          * copy and insert a break, or just keep track of it */
     713               0 :                         else if (text[current] == ' ') {
     714               0 :                                 if (current - laststart >= linelength) {
     715               0 :                                         memcpy(newtext+newtextlen, text+laststart, current-laststart);
     716               0 :                                         newtextlen += current - laststart;
     717               0 :                                         memcpy(newtext+newtextlen, breakchar, breakcharlen);
     718               0 :                                         newtextlen += breakcharlen;
     719               0 :                                         laststart = current + 1;
     720               0 :                                         chk--;
     721                 :                                 }
     722               0 :                                 lastspace = current;
     723                 :                         }
     724                 :                         /* if we are cutting, and we've accumulated enough
     725                 :                          * characters, and we haven't see a space for this line,
     726                 :                          * copy and insert a break. */
     727               0 :                         else if (current - laststart >= linelength
     728                 :                                         && docut && laststart >= lastspace) {
     729               0 :                                 memcpy(newtext+newtextlen, text+laststart, current-laststart);
     730               0 :                                 newtextlen += current - laststart;
     731               0 :                                 memcpy(newtext+newtextlen, breakchar, breakcharlen);
     732               0 :                                 newtextlen += breakcharlen;
     733               0 :                                 laststart = lastspace = current;
     734               0 :                                 chk--;
     735                 :                         }
     736                 :                         /* if the current word puts us over the linelength, copy
     737                 :                          * back up until the last space, insert a break, and move
     738                 :                          * up the laststart */
     739               0 :                         else if (current - laststart >= linelength
     740                 :                                         && laststart < lastspace) {
     741               0 :                                 memcpy(newtext+newtextlen, text+laststart, lastspace-laststart);
     742               0 :                                 newtextlen += lastspace - laststart;
     743               0 :                                 memcpy(newtext+newtextlen, breakchar, breakcharlen);
     744               0 :                                 newtextlen += breakcharlen;
     745               0 :                                 laststart = lastspace = lastspace + 1;
     746               0 :                                 chk--;
     747                 :                         }
     748                 :                 }
     749                 : 
     750                 :                 /* copy over any stragglers */
     751               0 :                 if (laststart != current) {
     752               0 :                         memcpy(newtext+newtextlen, text+laststart, current-laststart);
     753               0 :                         newtextlen += current - laststart;
     754                 :                 }
     755                 : 
     756               0 :                 newtext[newtextlen] = '\0';
     757                 :                 /* free unused memory */
     758               0 :                 newtext = erealloc(newtext, newtextlen+1);
     759                 : 
     760               0 :                 RETURN_STRINGL(newtext, newtextlen, 0);
     761                 :         }
     762                 : }
     763                 : /* }}} */
     764                 : 
     765                 : /* {{{ php_explode
     766                 :  */
     767                 : PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, int limit) 
     768            2295 : {
     769                 :         char *p1, *p2, *endp;
     770                 : 
     771            2295 :         endp = Z_STRVAL_P(str) + Z_STRLEN_P(str);
     772                 : 
     773            2295 :         p1 = Z_STRVAL_P(str);
     774            2295 :         p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp);
     775                 : 
     776            2295 :         if (p2 == NULL) {
     777              31 :                 add_next_index_stringl(return_value, p1, Z_STRLEN_P(str), 1);
     778                 :         } else {
     779                 :                 do {
     780            2666 :                         add_next_index_stringl(return_value, p1, p2 - p1, 1);
     781            2666 :                         p1 = p2 + Z_STRLEN_P(delim);
     782                 :                 } while ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL &&
     783            2666 :                                  (limit == -1 || --limit > 1));
     784                 : 
     785            2264 :                 if (p1 <= endp)
     786            2264 :                         add_next_index_stringl(return_value, p1, endp-p1, 1);
     787                 :         }
     788            2295 : }
     789                 : /* }}} */
     790                 : 
     791                 : /* {{{ php_explode_negative_limit
     792                 :  */
     793                 : PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_value, int limit) 
     794               0 : {
     795                 : #define EXPLODE_ALLOC_STEP 50
     796                 :         char *p1, *p2, *endp;
     797               0 :         int allocated = EXPLODE_ALLOC_STEP, found = 0, i = 0, to_return = 0;
     798               0 :         char **positions = safe_emalloc(allocated, sizeof(char *), 0);
     799                 :         
     800               0 :         endp = Z_STRVAL_P(str) + Z_STRLEN_P(str);
     801                 : 
     802               0 :         p1 = Z_STRVAL_P(str);
     803               0 :         p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp);
     804                 : 
     805               0 :         if (p2 == NULL) {
     806                 :                 /*
     807                 :                 do nothing since limit <= -1, thus if only one chunk - 1 + (limit) <= 0
     808                 :                 by doing nothing we return empty array
     809                 :                 */
     810                 :         } else {
     811               0 :                 positions[found++] = p1;
     812                 :                 do {
     813               0 :                         if (found >= allocated) {
     814               0 :                                 allocated = found + EXPLODE_ALLOC_STEP;/* make sure we have enough memory */
     815               0 :                                 positions = erealloc(positions, allocated*sizeof(char *));
     816                 :                         }
     817               0 :                         positions[found++] = p1 = p2 + Z_STRLEN_P(delim);
     818               0 :                 } while ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL);
     819                 :                 
     820               0 :                 to_return = limit + found;
     821                 :                 /* limit is at least -1 therefore no need of bounds checking : i will be always less than found */
     822               0 :                 for (i = 0;i < to_return;i++) { /* this checks also for to_return > 0 */
     823               0 :                         add_next_index_stringl(return_value, positions[i], 
     824                 :                                         (positions[i+1] - Z_STRLEN_P(delim)) - positions[i],
     825                 :                                         1
     826                 :                                 );
     827                 :                 }
     828                 :         }
     829               0 :         efree(positions);
     830                 : #undef EXPLODE_ALLOC_STEP
     831               0 : }
     832                 : /* }}} */
     833                 : 
     834                 : 
     835                 : /* {{{ proto array explode(string separator, string str [, int limit])
     836                 :    Splits a string on string separator and return array of components. If limit is positive only limit number of components is returned. If limit is negative all components except the last abs(limit) are returned. */
     837                 : PHP_FUNCTION(explode)
     838            2286 : {
     839            2286 :         zval **str, **delim, **zlimit = NULL;
     840            2286 :         int limit = -1;
     841            2286 :         int argc = ZEND_NUM_ARGS();
     842                 : 
     843            2286 :         if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &delim, &str, &zlimit) == FAILURE) {
     844               0 :                 WRONG_PARAM_COUNT;
     845                 :         }
     846            2286 :         convert_to_string_ex(str);
     847            2286 :         convert_to_string_ex(delim);
     848                 : 
     849            2286 :         if (argc > 2) {
     850            2240 :                 convert_to_long_ex(zlimit);
     851            2240 :                 limit = Z_LVAL_PP(zlimit);
     852                 :         }
     853                 : 
     854            2286 :         if (! Z_STRLEN_PP(delim)) {
     855               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter.");
     856               0 :                 RETURN_FALSE;
     857                 :         }
     858                 : 
     859            2286 :         array_init(return_value);
     860                 : 
     861            2286 :         if (! Z_STRLEN_PP(str)) {
     862               0 :                 add_next_index_stringl(return_value, "", sizeof("") - 1, 1);
     863               0 :                 return;
     864                 :         }
     865                 : 
     866                 : 
     867            2286 :         if (limit == 0 || limit == 1) {
     868               0 :                 add_index_stringl(return_value, 0, Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
     869            2286 :         } else if (limit < 0 && argc == 3) {
     870               0 :                 php_explode_negative_limit(*delim, *str, return_value, limit);
     871                 :         } else {
     872            2286 :                 php_explode(*delim, *str, return_value, limit);
     873                 :         }
     874                 : }
     875                 : /* }}} */
     876                 : 
     877                 : /* {{{ proto string join(array src, string glue)
     878                 :    An alias for implode */
     879                 : /* }}} */
     880                 : 
     881                 : /* {{{ php_implode
     882                 :  */
     883                 : PHPAPI void php_implode(zval *delim, zval *arr, zval *return_value TSRMLS_DC) 
     884               9 : {
     885                 :         zval         **tmp;
     886                 :         HashPosition   pos;
     887               9 :         smart_str      implstr = {0};
     888               9 :         int            numelems, i = 0;
     889                 :         zval tmp_val;
     890                 :         int str_len;
     891                 : 
     892               9 :         numelems = zend_hash_num_elements(Z_ARRVAL_P(arr));
     893                 : 
     894               9 :         if (numelems == 0) {
     895               0 :                 RETURN_EMPTY_STRING();
     896                 :         }
     897                 : 
     898               9 :         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
     899                 : 
     900             104 :         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **) &tmp, &pos) == SUCCESS) {
     901              86 :                 switch ((*tmp)->type) {
     902                 :                         case IS_STRING:
     903              86 :                                 smart_str_appendl(&implstr, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
     904              86 :                                 break;
     905                 : 
     906                 :                         case IS_LONG: {
     907                 :                                 char stmp[MAX_LENGTH_OF_LONG + 1];
     908               0 :                                 str_len = slprintf(stmp, sizeof(stmp), "%ld", Z_LVAL_PP(tmp));
     909               0 :                                 smart_str_appendl(&implstr, stmp, str_len);
     910                 :                         }
     911               0 :                                 break;
     912                 : 
     913                 :                         case IS_BOOL:
     914               0 :                                 if (Z_LVAL_PP(tmp) == 1) {
     915               0 :                                         smart_str_appendl(&implstr, "1", sizeof("1")-1);
     916                 :                                 }
     917               0 :                                 break;
     918                 :                         
     919                 :                         case IS_NULL:
     920               0 :                                 break;
     921                 : 
     922                 :                         case IS_DOUBLE: {
     923                 :                                 char *stmp;
     924               0 :                                 str_len = spprintf(&stmp, 0, "%.*G", (int) EG(precision), Z_DVAL_PP(tmp));
     925               0 :                                 smart_str_appendl(&implstr, stmp, str_len);
     926               0 :                                 efree(stmp);
     927                 :                         }
     928               0 :                                 break;
     929                 : 
     930                 :                         case IS_OBJECT: {
     931                 :                                 int copy;
     932                 :                                 zval expr;
     933               0 :                                 zend_make_printable_zval(*tmp, &expr, &copy);
     934               0 :                                 smart_str_appendl(&implstr, Z_STRVAL(expr), Z_STRLEN(expr));
     935               0 :                                 if (copy) {
     936               0 :                                         zval_dtor(&expr);
     937                 :                                 }
     938                 :                         }
     939               0 :                                 break;
     940                 : 
     941                 :                         default:
     942               0 :                                 tmp_val = **tmp;
     943               0 :                                 zval_copy_ctor(&tmp_val);
     944               0 :                                 convert_to_string(&tmp_val);
     945               0 :                                 smart_str_appendl(&implstr, Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
     946               0 :                                 zval_dtor(&tmp_val);
     947                 :                                 break;
     948                 :                                 
     949                 :                 }
     950                 : 
     951              86 :                 if (++i != numelems) {
     952              77 :                         smart_str_appendl(&implstr, Z_STRVAL_P(delim), Z_STRLEN_P(delim));
     953                 :                 }
     954              86 :                 zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
     955                 :         }
     956               9 :         smart_str_0(&implstr);
     957                 : 
     958               9 :         if (implstr.len) {
     959               9 :                 RETURN_STRINGL(implstr.c, implstr.len, 0);
     960                 :         } else {
     961               0 :                 smart_str_free(&implstr);
     962               0 :                 RETURN_EMPTY_STRING();
     963                 :         }
     964                 : }
     965                 : /* }}} */
     966                 : 
     967                 : /* {{{ proto string implode([string glue,] array pieces)
     968                 :    Joins array elements placing glue string between items and return one string */
     969                 : PHP_FUNCTION(implode)
     970               9 : {
     971               9 :         zval **arg1 = NULL, **arg2 = NULL, *delim, *arr;
     972               9 :         int argc = ZEND_NUM_ARGS();
     973                 :         HashPosition pos;
     974                 : 
     975               9 :         if (argc < 1 || argc > 2 ||
     976                 :                 zend_get_parameters_ex(argc, &arg1, &arg2) == FAILURE) {
     977               0 :                 WRONG_PARAM_COUNT;
     978                 :         }
     979                 : 
     980               9 :         if (argc == 1) {
     981               0 :                 if (Z_TYPE_PP(arg1) != IS_ARRAY) {
     982               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Argument to implode must be an array.");
     983               0 :                         return;
     984                 :                 }
     985                 : 
     986               0 :                 MAKE_STD_ZVAL(delim);
     987                 : #define _IMPL_EMPTY ""
     988               0 :                 ZVAL_STRINGL(delim, _IMPL_EMPTY, sizeof(_IMPL_EMPTY) - 1, 0);
     989                 : 
     990               0 :                 SEPARATE_ZVAL(arg1);
     991               0 :                 arr = *arg1;
     992                 :         } else {
     993               9 :                 if (Z_TYPE_PP(arg1) == IS_ARRAY) {
     994               0 :                         arr = *arg1;
     995               0 :                         convert_to_string_ex(arg2);
     996               0 :                         delim = *arg2;
     997               9 :                 } else if (Z_TYPE_PP(arg2) == IS_ARRAY) {
     998               9 :                         arr = *arg2;
     999               9 :                         convert_to_string_ex(arg1);
    1000               9 :                         delim = *arg1;
    1001                 :                 } else {
    1002               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad arguments.");
    1003               0 :                         return;
    1004                 :                 }
    1005                 :         }
    1006                 : 
    1007               9 :         pos = Z_ARRVAL_P(arr)->pInternalPointer;
    1008                 :         
    1009               9 :         php_implode(delim, arr, return_value TSRMLS_CC);
    1010                 : 
    1011               9 :         Z_ARRVAL_P(arr)->pInternalPointer = pos;
    1012                 : 
    1013               9 :         if (argc == 1) {
    1014               0 :                 FREE_ZVAL(delim);
    1015                 :         }
    1016                 : }
    1017                 : /* }}} */
    1018                 : 
    1019                 : #define STRTOK_TABLE(p) BG(strtok_table)[(unsigned char) *p]    
    1020                 : 
    1021                 : /* {{{ proto string strtok([string str,] string token)
    1022                 :    Tokenize a string */
    1023                 : PHP_FUNCTION(strtok)
    1024               0 : {
    1025                 :         zval **args[2];
    1026                 :         zval **tok, **str;
    1027                 :         char *token;
    1028                 :         char *token_end;
    1029                 :         char *p;
    1030                 :         char *pe;
    1031               0 :         int skipped = 0;
    1032                 :         
    1033               0 :         if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 2 || zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
    1034               0 :                 WRONG_PARAM_COUNT;
    1035                 :         }
    1036                 :                 
    1037               0 :         switch (ZEND_NUM_ARGS()) {
    1038                 :                 case 1:
    1039               0 :                         tok = args[0];
    1040               0 :                         break;
    1041                 : 
    1042                 :                 default:
    1043                 :                 case 2:
    1044               0 :                         str = args[0];
    1045               0 :                         tok = args[1];
    1046               0 :                         convert_to_string_ex(str);
    1047                 : 
    1048               0 :                         zval_add_ref(str);
    1049               0 :                         if (BG(strtok_zval)) {
    1050               0 :                                 zval_ptr_dtor(&BG(strtok_zval));
    1051                 :                         }
    1052               0 :                         BG(strtok_zval) = *str;
    1053               0 :                         BG(strtok_last) = BG(strtok_string) = Z_STRVAL_PP(str);
    1054               0 :                         BG(strtok_len) = Z_STRLEN_PP(str);
    1055                 :                         break;
    1056                 :         }
    1057                 :         
    1058               0 :         p = BG(strtok_last); /* Where we start to search */
    1059               0 :         pe = BG(strtok_string) + BG(strtok_len);
    1060                 : 
    1061               0 :         if (!p || p >= pe) {
    1062               0 :                 RETURN_FALSE;
    1063                 :         }
    1064                 : 
    1065               0 :         convert_to_string_ex(tok);
    1066                 :         
    1067               0 :         token = Z_STRVAL_PP(tok);
    1068               0 :         token_end = token + Z_STRLEN_PP(tok);
    1069                 : 
    1070               0 :         while (token < token_end) {
    1071               0 :                 STRTOK_TABLE(token++) = 1;
    1072                 :         }
    1073                 :         
    1074                 :         /* Skip leading delimiters */
    1075               0 :         while (STRTOK_TABLE(p)) {
    1076               0 :                 if (++p >= pe) {
    1077                 :                         /* no other chars left */
    1078               0 :                         BG(strtok_last) = NULL;
    1079               0 :                         RETVAL_FALSE;
    1080               0 :                         goto restore;
    1081                 :                 }
    1082               0 :                 skipped++;
    1083                 :         }
    1084                 :         
    1085                 :         /* We know at this place that *p is no delimiter, so skip it */ 
    1086               0 :         while (++p < pe) {
    1087               0 :                 if (STRTOK_TABLE(p)) {
    1088               0 :                         goto return_token;      
    1089                 :                 }
    1090                 :         }
    1091                 :         
    1092               0 :         if (p - BG(strtok_last)) {
    1093               0 : return_token:
    1094               0 :                 RETVAL_STRINGL(BG(strtok_last) + skipped, (p - BG(strtok_last)) - skipped, 1);
    1095               0 :                 BG(strtok_last) = p + 1;
    1096                 :         } else {
    1097               0 :                 RETVAL_FALSE;
    1098               0 :                 BG(strtok_last) = NULL;
    1099                 :         }
    1100                 : 
    1101                 :         /* Restore table -- usually faster then memset'ing the table on every invocation */
    1102               0 : restore:
    1103               0 :         token = Z_STRVAL_PP(tok);
    1104                 :         
    1105               0 :         while (token < token_end) {
    1106               0 :                 STRTOK_TABLE(token++) = 0;
    1107                 :         }
    1108                 : }
    1109                 : /* }}} */
    1110                 : 
    1111                 : /* {{{ php_strtoupper
    1112                 :  */
    1113                 : PHPAPI char *php_strtoupper(char *s, size_t len)
    1114               0 : {
    1115                 :         unsigned char *c, *e;
    1116                 :         
    1117               0 :         c = s;
    1118               0 :         e = c+len;
    1119                 : 
    1120               0 :         while (c < e) {
    1121               0 :                 *c = toupper(*c);
    1122               0 :                 c++;
    1123                 :         }
    1124               0 :         return s;
    1125                 : }
    1126                 : /* }}} */
    1127                 : 
    1128                 : /* {{{ proto string strtoupper(string str)
    1129                 :    Makes a string uppercase */
    1130                 : PHP_FUNCTION(strtoupper)
    1131               0 : {
    1132                 :         zval **arg;
    1133                 :         
    1134               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg)) {
    1135               0 :                 WRONG_PARAM_COUNT;
    1136                 :         }
    1137               0 :         convert_to_string_ex(arg);
    1138                 : 
    1139               0 :         RETVAL_ZVAL(*arg, 1, 0);
    1140               0 :         php_strtoupper(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value));
    1141                 : }
    1142                 : /* }}} */
    1143                 : 
    1144                 : /* {{{ php_strtolower
    1145                 :  */
    1146                 : PHPAPI char *php_strtolower(char *s, size_t len)
    1147            2201 : {
    1148                 :         unsigned char *c, *e;
    1149                 :         
    1150            2201 :         c = s;
    1151            2201 :         e = c+len;
    1152                 : 
    1153           36672 :         while (c < e) {
    1154           32270 :                 *c = tolower(*c);
    1155           32270 :                 c++;
    1156                 :         }
    1157            2201 :         return s;
    1158                 : }
    1159                 : /* }}} */
    1160                 : 
    1161                 : /* {{{ proto string strtolower(string str)
    1162                 :    Makes a string lowercase */
    1163                 : PHP_FUNCTION(strtolower)
    1164            2201 : {
    1165                 :         zval **str;
    1166                 :         char *ret;
    1167                 :         
    1168            2201 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str)) {
    1169               0 :                 WRONG_PARAM_COUNT;
    1170                 :         }
    1171            2201 :         convert_to_string_ex(str);
    1172                 : 
    1173            2201 :         RETVAL_ZVAL(*str, 1, 0);
    1174            2201 :         ret = php_strtolower(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value));
    1175                 : }
    1176                 : /* }}} */
    1177                 : 
    1178                 : /* {{{ php_basename
    1179                 :  */
    1180                 : PHPAPI void php_basename(char *s, size_t len, char *suffix, size_t sufflen, char **p_ret, size_t *p_len TSRMLS_DC)
    1181             110 : {
    1182             110 :         char *ret = NULL, *c, *comp, *cend;
    1183                 :         size_t inc_len, cnt;
    1184                 :         int state;
    1185                 : 
    1186             110 :         c = comp = cend = s;
    1187             110 :         cnt = len;
    1188             110 :         state = 0;
    1189            5848 :         while (cnt > 0) {
    1190            5628 :                 inc_len = (*c == '\0' ? 1: php_mblen(c, cnt));
    1191                 : 
    1192            5628 :                 switch (inc_len) {
    1193                 :                         case -2:
    1194                 :                         case -1:
    1195               0 :                                 inc_len = 1;
    1196               0 :                                 php_mblen(NULL, 0);
    1197               0 :                                 break;
    1198                 :                         case 0:
    1199               0 :                                 goto quit_loop;
    1200                 :                         case 1:
    1201                 : #if defined(PHP_WIN32) || defined(NETWARE)
    1202                 :                                 if (*c == '/' || *c == '\\') {
    1203                 : #else
    1204            5628 :                                 if (*c == '/') {
    1205                 : #endif
    1206             763 :                                         if (state == 1) {
    1207             654 :                                                 state = 0;
    1208             654 :                                                 cend = c;
    1209                 :                                         }
    1210                 :                                 } else {
    1211            4865 :                                         if (state == 0) {
    1212             764 :                                                 comp = c;
    1213             764 :                                                 state = 1;
    1214                 :                                         }
    1215                 :                                 }
    1216            5628 :                                 break;
    1217                 :                         default:
    1218               0 :                                 if (state == 0) {
    1219               0 :                                         comp = c;
    1220               0 :                                         state = 1;
    1221                 :                                 }
    1222                 :                                 break;
    1223                 :                 }
    1224            5628 :                 c += inc_len;
    1225            5628 :                 cnt -= inc_len;
    1226                 :         }
    1227                 : 
    1228             110 : quit_loop:
    1229             110 :         if (state == 1) {
    1230             110 :                 cend = c;
    1231                 :         }
    1232             110 :         if (suffix != NULL && sufflen < (uint)(cend - comp) &&
    1233                 :                         memcmp(cend - sufflen, suffix, sufflen) == 0) {
    1234             109 :                 cend -= sufflen;
    1235                 :         }
    1236                 : 
    1237             110 :         len = cend - comp;
    1238                 : 
    1239             110 :         if (p_ret) {
    1240             110 :                 ret = emalloc(len + 1);
    1241             110 :                 memcpy(ret, comp, len);
    1242             110 :                 ret[len] = '\0';
    1243             110 :                 *p_ret = ret;
    1244                 :         }
    1245             110 :         if (p_len) {
    1246             110 :                 *p_len = len;
    1247                 :         }
    1248             110 : }
    1249                 : /* }}} */
    1250                 : 
    1251                 : /* {{{ proto string basename(string path [, string suffix])
    1252                 :    Returns the filename component of the path */
    1253                 : PHP_FUNCTION(basename)
    1254             109 : {
    1255             109 :         char *string, *suffix = NULL, *ret;
    1256             109 :         int   string_len, suffix_len = 0;
    1257                 :         size_t ret_len;
    1258                 : 
    1259             109 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &string, &string_len, &suffix, &suffix_len) == FAILURE) {
    1260               0 :                 return;
    1261                 :         }
    1262                 : 
    1263             109 :         php_basename(string, string_len, suffix, suffix_len, &ret, &ret_len TSRMLS_CC);
    1264             109 :         RETURN_STRINGL(ret, (int)ret_len, 0);
    1265                 : }
    1266                 : /* }}} */
    1267                 : 
    1268                 : /* {{{ php_dirname
    1269                 :    Returns directory name component of path */
    1270                 : PHPAPI size_t php_dirname(char *path, size_t len)
    1271             223 : {
    1272             223 :         register char *end = path + len - 1;
    1273             223 :         unsigned int len_adjust = 0;
    1274                 : 
    1275                 : #ifdef PHP_WIN32
    1276                 :         /* Note that on Win32 CWD is per drive (heritage from CP/M).
    1277                 :          * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
    1278                 :          */
    1279                 :         if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
    1280                 :                 /* Skip over the drive spec (if any) so as not to change */
    1281                 :                 path += 2;
    1282                 :                 len_adjust += 2;
    1283                 :                 if (2 == len) {
    1284                 :                         /* Return "c:" on Win32 for dirname("c:").
    1285                 :                          * It would be more consistent to return "c:." 
    1286                 :                          * but that would require making the string *longer*.
    1287                 :                          */
    1288                 :                         return len;
    1289                 :                 }
    1290                 :         }
    1291                 : #elif defined(NETWARE)
    1292                 :         /*
    1293                 :          * Find the first occurence of : from the left 
    1294                 :          * move the path pointer to the position just after :
    1295                 :          * increment the len_adjust to the length of path till colon character(inclusive)
    1296                 :          * If there is no character beyond : simple return len
    1297                 :          */
    1298                 :         char *colonpos = NULL;
    1299                 :         colonpos = strchr(path, ':');
    1300                 :         if(colonpos != NULL) {
    1301                 :                 len_adjust = ((colonpos - path) + 1);
    1302                 :                 path += len_adjust;
    1303                 :                 if(len_adjust == len) {
    1304                 :                 return len;
    1305                 :                 }
    1306                 :         }
    1307                 : #endif
    1308                 : 
    1309             223 :         if (len == 0) {
    1310                 :                 /* Illegal use of this function */
    1311               0 :                 return 0;
    1312                 :         }
    1313                 : 
    1314                 :         /* Strip trailing slashes */
    1315             446 :         while (end >= path && IS_SLASH_P(end)) {
    1316               0 :                 end--;
    1317                 :         }
    1318             223 :         if (end < path) {
    1319                 :                 /* The path only contained slashes */
    1320               0 :                 path[0] = DEFAULT_SLASH;
    1321               0 :                 path[1] = '\0';
    1322               0 :                 return 1 + len_adjust;
    1323                 :         }
    1324                 : 
    1325                 :         /* Strip filename */
    1326            4189 :         while (end >= path && !IS_SLASH_P(end)) {
    1327            3743 :                 end--;
    1328                 :         }
    1329             223 :         if (end < path) {
    1330                 :                 /* No slash found, therefore return '.' */
    1331                 : #ifdef NETWARE
    1332                 :                 if(len_adjust == 0) {
    1333                 :                         path[0] = '.';
    1334                 :                         path[1] = '\0';
    1335                 :                         return 1; //only one character
    1336                 :                 } 
    1337                 :                 else {
    1338                 :                         path[0] = '\0';
    1339                 :                         return len_adjust;
    1340                 :                 }
    1341                 : #else
    1342               0 :                 path[0] = '.';
    1343               0 :                 path[1] = '\0';
    1344               0 :                 return 1 + len_adjust;
    1345                 : #endif
    1346                 :         }
    1347                 : 
    1348                 :         /* Strip slashes which came before the file name */
    1349             669 :         while (end >= path && IS_SLASH_P(end)) {
    1350             223 :                 end--;
    1351                 :         }
    1352             223 :         if (end < path) {
    1353               0 :                 path[0] = DEFAULT_SLASH;
    1354               0 :                 path[1] = '\0';
    1355               0 :                 return 1 + len_adjust;
    1356                 :         }
    1357             223 :         *(end+1) = '\0';
    1358                 : 
    1359             223 :         return (size_t)(end + 1 - path) + len_adjust;
    1360                 : }
    1361                 : /* }}} */
    1362                 : 
    1363                 : /* {{{ proto string dirname(string path)
    1364                 :    Returns the directory name component of the path */
    1365                 : PHP_FUNCTION(dirname)
    1366             222 : {
    1367                 :         zval **str;
    1368                 :         char *ret;
    1369                 :         size_t ret_len;
    1370                 : 
    1371             222 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {
    1372               0 :                 WRONG_PARAM_COUNT;
    1373                 :         }
    1374             222 :         convert_to_string_ex(str);
    1375                 : 
    1376             222 :         ret = estrndup(Z_STRVAL_PP(str), Z_STRLEN_PP(str));
    1377             222 :         ret_len = php_dirname(ret, Z_STRLEN_PP(str));
    1378                 : 
    1379             222 :         RETURN_STRINGL(ret, ret_len, 0);
    1380                 : }
    1381                 : /* }}} */
    1382                 : 
    1383                 : /* {{{ proto array pathinfo(string path[, int options])
    1384                 :    Returns information about a certain string */
    1385                 : PHP_FUNCTION(pathinfo)
    1386               0 : {
    1387                 :         zval *tmp;
    1388               0 :         char *path, *ret = NULL;
    1389                 :         int path_len, have_basename;
    1390                 :         size_t ret_len;
    1391               0 :         long opt = PHP_PATHINFO_ALL;
    1392                 : 
    1393               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &path, &path_len, &opt) == FAILURE) {
    1394               0 :                 return;
    1395                 :         }
    1396                 : 
    1397               0 :         have_basename = ((opt & PHP_PATHINFO_BASENAME) == PHP_PATHINFO_BASENAME);
    1398                 :         
    1399               0 :         MAKE_STD_ZVAL(tmp);
    1400               0 :         array_init(tmp);
    1401                 :         
    1402               0 :         if ((opt & PHP_PATHINFO_DIRNAME) == PHP_PATHINFO_DIRNAME) {
    1403               0 :                 ret = estrndup(path, path_len);
    1404               0 :                 php_dirname(ret, path_len);
    1405               0 :                 if (*ret) {
    1406               0 :                         add_assoc_string(tmp, "dirname", ret, 1);
    1407                 :                 }
    1408               0 :                 efree(ret);
    1409               0 :                 ret = NULL;
    1410                 :         }
    1411                 :         
    1412               0 :         if (have_basename) {
    1413               0 :                 php_basename(path, path_len, NULL, 0, &ret, &ret_len TSRMLS_CC);
    1414               0 :                 add_assoc_stringl(tmp, "basename", ret, ret_len, 0);
    1415                 :         }
    1416                 :         
    1417               0 :         if ((opt & PHP_PATHINFO_EXTENSION) == PHP_PATHINFO_EXTENSION) {
    1418                 :                 char *p;
    1419                 :                 int idx;
    1420                 : 
    1421               0 :                 if (!have_basename) {
    1422               0 :                         php_basename(path, path_len, NULL, 0, &ret, &ret_len TSRMLS_CC);
    1423                 :                 }
    1424                 : 
    1425               0 :                 p = zend_memrchr(ret, '.', ret_len);
    1426                 : 
    1427               0 :                 if (p) {
    1428               0 :                         idx = p - ret;
    1429               0 :                         add_assoc_stringl(tmp, "extension", ret + idx + 1, ret_len - idx - 1, 1);
    1430                 :                 }
    1431                 :         }
    1432                 :         
    1433               0 :         if ((opt & PHP_PATHINFO_FILENAME) == PHP_PATHINFO_FILENAME) {
    1434                 :                 char *p;
    1435                 :                 int idx;
    1436                 : 
    1437                 :                 /* Have we alrady looked up the basename? */
    1438               0 :                 if (!have_basename && !ret) {
    1439               0 :                         php_basename(path, path_len, NULL, 0, &ret, &ret_len TSRMLS_CC);
    1440                 :                 }
    1441                 : 
    1442               0 :                 p = zend_memrchr(ret, '.', ret_len);
    1443                 : 
    1444               0 :                 idx = p ? (p - ret) : ret_len;
    1445               0 :                 add_assoc_stringl(tmp, "filename", ret, idx, 1);
    1446                 :         }
    1447                 : 
    1448               0 :         if (!have_basename && ret) {
    1449               0 :                 efree(ret);
    1450                 :         }
    1451                 : 
    1452               0 :         if (opt == PHP_PATHINFO_ALL) {
    1453               0 :                 RETURN_ZVAL(tmp, 0, 1);
    1454                 :         } else {
    1455                 :                 zval **element;
    1456               0 :                 if (zend_hash_get_current_data(Z_ARRVAL_P(tmp), (void **) &element) == SUCCESS) {
    1457               0 :                         RETVAL_ZVAL(*element, 1, 0);
    1458                 :                 } else {
    1459               0 :                         ZVAL_EMPTY_STRING(return_value);
    1460                 :                 }
    1461                 :         }
    1462                 : 
    1463               0 :         zval_ptr_dtor(&tmp);
    1464                 : }
    1465                 : /* }}} */
    1466                 : 
    1467                 : /* {{{ php_stristr
    1468                 :    case insensitve strstr */
    1469                 : PHPAPI char *php_stristr(unsigned char *s, unsigned char *t, size_t s_len, size_t t_len)
    1470               0 : {
    1471               0 :         php_strtolower(s, s_len);
    1472               0 :         php_strtolower(t, t_len);
    1473               0 :         return php_memnstr(s, t, t_len, s + s_len);
    1474                 : }
    1475                 : /* }}} */
    1476                 : 
    1477                 : /* {{{ php_strspn
    1478                 :  */
    1479                 : PHPAPI size_t php_strspn(char *s1, char *s2, char *s1_end, char *s2_end)
    1480               0 : {
    1481               0 :         register const char *p = s1, *spanp;
    1482               0 :         register char c = *p;
    1483                 : 
    1484               0 : cont:
    1485               0 :         for (spanp = s2; p != s1_end && spanp != s2_end;) {
    1486               0 :                 if (*spanp++ == c) {
    1487               0 :                         c = *(++p);
    1488               0 :                         goto cont;
    1489                 :                 }
    1490                 :         }
    1491               0 :         return (p - s1);
    1492                 : }
    1493                 : /* }}} */
    1494                 : 
    1495                 : /* {{{ php_strcspn
    1496                 :  */
    1497                 : PHPAPI size_t php_strcspn(char *s1, char *s2, char *s1_end, char *s2_end)
    1498               0 : {
    1499                 :         register const char *p, *spanp;
    1500               0 :         register char c = *s1;
    1501                 : 
    1502               0 :         for (p = s1;;) {
    1503               0 :                 spanp = s2;
    1504                 :                 do {
    1505               0 :                         if (*spanp == c || p == s1_end) {
    1506               0 :                                 return p - s1;
    1507                 :                         }
    1508               0 :                 } while (spanp++ < (s2_end - 1));
    1509               0 :                 c = *++p;
    1510               0 :         }
    1511                 :         /* NOTREACHED */
    1512                 : }
    1513                 : /* }}} */
    1514                 : 
    1515                 : /* {{{ proto string stristr(string haystack, string needle)
    1516                 :    Finds first occurrence of a string within another, case insensitive */
    1517                 : PHP_FUNCTION(stristr)
    1518               0 : {
    1519                 :         zval **haystack, **needle;
    1520               0 :         char *found = NULL;
    1521                 :         int  found_offset;
    1522                 :         char *haystack_orig;
    1523                 :         char needle_char[2];
    1524                 :         
    1525               0 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &haystack, &needle) == FAILURE) {
    1526               0 :                 WRONG_PARAM_COUNT;
    1527                 :         }
    1528                 : 
    1529               0 :         SEPARATE_ZVAL(haystack);
    1530               0 :         SEPARATE_ZVAL(needle);
    1531                 :         
    1532               0 :         convert_to_string_ex(haystack);
    1533                 : 
    1534               0 :         haystack_orig = estrndup(Z_STRVAL_PP(haystack), Z_STRLEN_PP(haystack));
    1535                 : 
    1536               0 :         if (Z_TYPE_PP(needle) == IS_STRING) {
    1537               0 :                 if (!Z_STRLEN_PP(needle)) {
    1538               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter.");
    1539               0 :                         efree(haystack_orig);
    1540               0 :                         RETURN_FALSE;
    1541                 :                 }
    1542                 : 
    1543               0 :                 found = php_stristr(Z_STRVAL_PP(haystack),
    1544                 :                                                         Z_STRVAL_PP(needle),
    1545                 :                                                         Z_STRLEN_PP(haystack),
    1546                 :                                                         Z_STRLEN_PP(needle));
    1547                 :         } else {
    1548               0 :                 convert_to_long_ex(needle);
    1549               0 :                 needle_char[0] = (char) Z_LVAL_PP(needle);
    1550               0 :                 needle_char[1] = 0;
    1551                 : 
    1552               0 :                 found = php_stristr(Z_STRVAL_PP(haystack),
    1553                 :                                                         needle_char,
    1554                 :                                                         Z_STRLEN_PP(haystack),
    1555                 :                                                         1);
    1556                 :         }
    1557                 : 
    1558               0 :         if (found) {
    1559               0 :                 found_offset = found - Z_STRVAL_PP(haystack);
    1560               0 :                 RETVAL_STRINGL(haystack_orig + found_offset, Z_STRLEN_PP(haystack) - found_offset, 1);
    1561                 :         } else {
    1562               0 :                 RETVAL_FALSE;
    1563                 :         }
    1564                 : 
    1565               0 :         efree(haystack_orig);
    1566                 : }
    1567                 : /* }}} */
    1568                 : 
    1569                 : /* {{{ proto string strstr(string haystack, string needle)
    1570                 :    Finds first occurrence of a string within another */
    1571                 : PHP_FUNCTION(strstr)
    1572               0 : {
    1573                 :         zval **haystack, **needle;
    1574               0 :         char *found = NULL;
    1575                 :         char needle_char[2];
    1576                 :         long found_offset;
    1577                 :         
    1578               0 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &haystack, &needle) == FAILURE) {
    1579               0 :                 WRONG_PARAM_COUNT;
    1580                 :         }
    1581                 : 
    1582               0 :         convert_to_string_ex(haystack);
    1583                 : 
    1584               0 :         if (Z_TYPE_PP(needle) == IS_STRING) {
    1585               0 :                 if (!Z_STRLEN_PP(needle)) {
    1586               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter.");
    1587               0 :                         RETURN_FALSE;
    1588                 :                 }
    1589                 : 
    1590               0 :                 found = php_memnstr(Z_STRVAL_PP(haystack), 
    1591                 :                                     Z_STRVAL_PP(needle),
    1592                 :                                     Z_STRLEN_PP(needle), 
    1593                 :                                     Z_STRVAL_PP(haystack) + Z_STRLEN_PP(haystack));
    1594                 :         } else {
    1595               0 :                 convert_to_long_ex(needle);
    1596               0 :                 needle_char[0] = (char) Z_LVAL_PP(needle);
    1597               0 :                 needle_char[1] = 0;
    1598                 : 
    1599               0 :                 found = php_memnstr(Z_STRVAL_PP(haystack), 
    1600                 :                                                         needle_char,
    1601                 :                                                         1,
    1602                 :                                     Z_STRVAL_PP(haystack) + Z_STRLEN_PP(haystack));
    1603                 :         }
    1604                 : 
    1605               0 :         if (found) {
    1606               0 :                 found_offset = found - Z_STRVAL_PP(haystack);
    1607               0 :                 RETURN_STRINGL(found, Z_STRLEN_PP(haystack) - found_offset, 1);
    1608                 :         } else {
    1609               0 :                 RETURN_FALSE;
    1610                 :         }
    1611                 : }
    1612                 : /* }}} */
    1613                 : 
    1614                 : /* {{{ proto string strchr(string haystack, string needle)
    1615                 :    An alias for strstr */
    1616                 : /* }}} */
    1617                 : 
    1618                 : /* {{{ proto int strpos(string haystack, string needle [, int offset])
    1619                 :    Finds position of first occurrence of a string within another */
    1620                 : PHP_FUNCTION(strpos)
    1621            3735 : {
    1622                 :         zval **haystack, **needle, **z_offset;
    1623            3735 :         char *found = NULL;
    1624                 :         char  needle_char[2];
    1625            3735 :         int   offset = 0;
    1626            3735 :         int   argc = ZEND_NUM_ARGS();
    1627                 : 
    1628            3735 :         if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &haystack, &needle, &z_offset) == FAILURE) {
    1629               0 :                 WRONG_PARAM_COUNT;
    1630                 :         }
    1631            3735 :         convert_to_string_ex(haystack);
    1632                 : 
    1633            3735 :         if (argc > 2) {
    1634               0 :                 convert_to_long_ex(z_offset);
    1635               0 :                 offset = Z_LVAL_PP(z_offset);
    1636                 :         }
    1637                 : 
    1638            3735 :         if (offset < 0 || offset > Z_STRLEN_PP(haystack)) {
    1639               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset not contained in string.");
    1640               0 :                 RETURN_FALSE;
    1641                 :         }
    1642                 : 
    1643            3735 :         if (Z_TYPE_PP(needle) == IS_STRING) {
    1644            3735 :                 if (!Z_STRLEN_PP(needle)) {
    1645               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty delimiter.");
    1646               0 :                         RETURN_FALSE;
    1647                 :                 }
    1648                 : 
    1649            3735 :                 found = php_memnstr(Z_STRVAL_PP(haystack) + offset,
    1650                 :                                         Z_STRVAL_PP(needle),
    1651                 :                                         Z_STRLEN_PP(needle),
    1652                 :                                         Z_STRVAL_PP(haystack) + Z_STRLEN_PP(haystack));
    1653                 :         } else {
    1654               0 :                 convert_to_long_ex(needle);
    1655               0 :                 needle_char[0] = (char) Z_LVAL_PP(needle);
    1656               0 :                 needle_char[1] = 0;
    1657                 : 
    1658               0 :                 found = php_memnstr(Z_STRVAL_PP(haystack) + offset,
    1659                 :                                                         needle_char,
    1660                 :                                                         1,
    1661                 :                                     Z_STRVAL_PP(haystack) + Z_STRLEN_PP(haystack));
    1662                 :         }
    1663                 : 
    1664            3735 :         if (found) {
    1665            2217 :                 RETURN_LONG(found - Z_STRVAL_PP(haystack));
    1666                 :         } else {
    1667            1518 :                 RETURN_FALSE;
    1668                 :         }
    1669                 : }
    1670                 : /* }}} */
    1671                 : 
    1672                 : /* {{{ proto int stripos(string haystack, string needle [, int offset])
    1673                 :    Finds position of first occurrence of a string within another, case insensitive */
    1674                 : PHP_FUNCTION(stripos)
    1675               0 : {
    1676               0 :         char *found = NULL;
    1677                 :         char *haystack;
    1678                 :         int haystack_len;
    1679               0 :         long offset = 0;
    1680               0 :         char *needle_dup = NULL, *haystack_dup;
    1681                 :         char needle_char[2];
    1682                 :         zval *needle;
    1683                 : 
    1684               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &haystack, &haystack_len, &needle, &offset) == FAILURE) {
    1685               0 :                 return;
    1686                 :         }
    1687                 : 
    1688               0 :         if (offset < 0 || offset > haystack_len) {
    1689               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset not contained in string.");
    1690               0 :                 RETURN_FALSE;
    1691                 :         }
    1692                 : 
    1693               0 :         if (haystack_len == 0) {
    1694               0 :                 RETURN_FALSE;
    1695                 :         }
    1696                 : 
    1697               0 :         haystack_dup = estrndup(haystack, haystack_len);
    1698               0 :         php_strtolower(haystack_dup, haystack_len);
    1699                 : 
    1700               0 :         if (Z_TYPE_P(needle) == IS_STRING) {
    1701               0 :                 if (Z_STRLEN_P(needle) == 0 || Z_STRLEN_P(needle) > haystack_len) {
    1702               0 :                         efree(haystack_dup);
    1703               0 :                         RETURN_FALSE;
    1704                 :                 }
    1705                 : 
    1706               0 :                 needle_dup = estrndup(Z_STRVAL_P(needle), Z_STRLEN_P(needle));
    1707               0 :                 php_strtolower(needle_dup, Z_STRLEN_P(needle));
    1708               0 :                 found = php_memnstr(haystack_dup + offset, needle_dup, Z_STRLEN_P(needle), haystack_dup + haystack_len);
    1709                 :         } else {
    1710               0 :                 switch (Z_TYPE_P(needle)) {
    1711                 :                         case IS_LONG:
    1712                 :                         case IS_BOOL:
    1713               0 :                                 needle_char[0] = tolower((char) Z_LVAL_P(needle));
    1714               0 :                                 break;
    1715                 :                         case IS_DOUBLE:
    1716               0 :                                 needle_char[0] = tolower((char) Z_DVAL_P(needle));
    1717               0 :                                 break;
    1718                 :                         default:
    1719               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "needle is not a string or an integer.");
    1720               0 :                                 efree(haystack_dup);
    1721               0 :                                 RETURN_FALSE;
    1722                 :                                 break;
    1723                 :                                         
    1724                 :                 }
    1725               0 :                 needle_char[1] = '\0';
    1726               0 :                 found = php_memnstr(haystack_dup + offset, 
    1727                 :                                                         needle_char, 
    1728                 :                                                         sizeof(needle_char) - 1, 
    1729                 :                                                         haystack_dup + haystack_len);
    1730                 :         }
    1731                 : 
    1732               0 :         efree(haystack_dup);
    1733               0 :         if (needle_dup) {
    1734               0 :                 efree(needle_dup);
    1735                 :         }
    1736                 : 
    1737               0 :         if (found) {
    1738               0 :                 RETURN_LONG(found - haystack_dup);
    1739                 :         } else {
    1740               0 :                 RETURN_FALSE;
    1741                 :         }
    1742                 : }
    1743                 : /* }}} */
    1744                 : 
    1745                 : /* {{{ proto int strrpos(string haystack, string needle [, int offset])
    1746                 :    Finds position of last occurrence of a string within another string */
    1747                 : PHP_FUNCTION(strrpos)
    1748               0 : {
    1749                 :         zval **zneedle;
    1750                 :         char *needle, *haystack;
    1751                 :         int needle_len, haystack_len;
    1752               0 :         long offset = 0;
    1753                 :         char *p, *e, ord_needle[2];
    1754                 : 
    1755               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sZ|l", &haystack, &haystack_len, &zneedle, &offset) == FAILURE) {
    1756               0 :                 RETURN_FALSE;
    1757                 :         }
    1758                 : 
    1759               0 :         if (Z_TYPE_PP(zneedle) == IS_STRING) {
    1760               0 :                 needle = Z_STRVAL_PP(zneedle);
    1761               0 :                 needle_len = Z_STRLEN_PP(zneedle);
    1762                 :         } else {
    1763               0 :                 convert_to_long_ex(zneedle);
    1764               0 :                 ord_needle[0] = (char)(Z_LVAL_PP(zneedle) & 0xFF);
    1765               0 :                 ord_needle[1] = '\0';
    1766               0 :                 needle = ord_needle;
    1767               0 :                 needle_len = 1;
    1768                 :         }
    1769                 : 
    1770               0 :         if ((haystack_len == 0) || (needle_len == 0)) {
    1771               0 :                 RETURN_FALSE;
    1772                 :         }
    1773                 : 
    1774               0 :         if (offset >= 0) {
    1775               0 :                 if (offset > haystack_len) {
    1776               0 :                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Offset is greater than the length of haystack string");
    1777               0 :                         RETURN_FALSE;
    1778                 :                 }
    1779               0 :                 p = haystack + offset;
    1780               0 :                 e = haystack + haystack_len - needle_len;
    1781                 :         } else {
    1782               0 :                 if (-offset > haystack_len) {
    1783               0 :                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Offset is greater than the length of haystack string");
    1784               0 :                         RETURN_FALSE;
    1785                 :                 }
    1786                 : 
    1787               0 :                 p = haystack;
    1788               0 :                 if (needle_len > -offset) {
    1789               0 :                         e = haystack + haystack_len - needle_len;
    1790                 :                 } else {
    1791               0 :                         e = haystack + haystack_len + offset;
    1792                 :                 }
    1793                 :         }
    1794                 : 
    1795               0 :         if (needle_len == 1) {
    1796                 :                 /* Single character search can shortcut memcmps */
    1797               0 :                 while (e >= p) {
    1798               0 :                         if (*e == *needle) {
    1799               0 :                                 RETURN_LONG(e - p + (offset > 0 ? offset : 0));
    1800                 :                         }
    1801               0 :                         e--;
    1802                 :                 }
    1803               0 :                 RETURN_FALSE;
    1804                 :         }
    1805                 : 
    1806               0 :         while (e >= p) {
    1807               0 :                 if (memcmp(e, needle, needle_len) == 0) {
    1808               0 :                         RETURN_LONG(e - p + (offset > 0 ? offset : 0));
    1809                 :                 }
    1810               0 :                 e--;
    1811                 :         }
    1812                 : 
    1813               0 :         RETURN_FALSE;
    1814                 : }
    1815                 : /* }}} */
    1816                 : 
    1817                 : /* {{{ proto int strripos(string haystack, string needle [, int offset])
    1818                 :    Finds position of last occurrence of a string within another string */
    1819                 : PHP_FUNCTION(strripos)
    1820               0 : {
    1821                 :         zval **zneedle;
    1822                 :         char *needle, *haystack;
    1823                 :         int needle_len, haystack_len;
    1824               0 :         long offset = 0;
    1825                 :         char *p, *e, ord_needle[2];
    1826                 :         char *needle_dup, *haystack_dup;
    1827                 : 
    1828               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sZ|l", &haystack, &haystack_len, &zneedle, &offset) == FAILURE) {
    1829               0 :                 RETURN_FALSE;
    1830                 :         }
    1831                 : 
    1832               0 :         if (Z_TYPE_PP(zneedle) == IS_STRING) {
    1833               0 :                 needle = Z_STRVAL_PP(zneedle);
    1834               0 :                 needle_len = Z_STRLEN_PP(zneedle);
    1835                 :         } else {
    1836               0 :                 convert_to_long_ex(zneedle);
    1837               0 :                 ord_needle[0] = (char)(Z_LVAL_PP(zneedle) & 0xFF);
    1838               0 :                 ord_needle[1] = '\0';
    1839               0 :                 needle = ord_needle;
    1840               0 :                 needle_len = 1;
    1841                 :         }
    1842                 : 
    1843               0 :         if ((haystack_len == 0) || (needle_len == 0)) {
    1844               0 :                 RETURN_FALSE;
    1845                 :         }
    1846                 : 
    1847               0 :         if (needle_len == 1) {
    1848                 :                 /* Single character search can shortcut memcmps 
    1849                 :                    Can also avoid tolower emallocs */
    1850               0 :                 if (offset >= 0) {
    1851               0 :                         if (offset > haystack_len) {
    1852               0 :                                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Offset is greater than the length of haystack string");
    1853               0 :                                 RETURN_FALSE;
    1854                 :                         }
    1855               0 :                         p = haystack + offset;
    1856               0 :                         e = haystack + haystack_len - 1;
    1857                 :                 } else {
    1858               0 :                         p = haystack;
    1859               0 :                         if (-offset > haystack_len) {
    1860               0 :                                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Offset is greater than the length of haystack string");
    1861               0 :                                 RETURN_FALSE;
    1862                 :                         } else {
    1863               0 :                                 e = haystack + haystack_len + offset;
    1864                 :                         }
    1865                 :                 }
    1866                 :                 /* Borrow that ord_needle buffer to avoid repeatedly tolower()ing needle */
    1867               0 :                 *ord_needle = tolower(*needle);
    1868               0 :                 while (e >= p) {
    1869               0 :                         if (tolower(*e) == *ord_needle) {
    1870               0 :                                 RETURN_LONG(e - p + (offset > 0 ? offset : 0));
    1871                 :                         }
    1872               0 :                         e--;
    1873                 :                 }
    1874               0 :                 RETURN_FALSE;
    1875                 :         }
    1876                 : 
    1877               0 :         needle_dup = estrndup(needle, needle_len);
    1878               0 :         php_strtolower(needle_dup, needle_len);
    1879               0 :         haystack_dup = estrndup(haystack, haystack_len);
    1880               0 :         php_strtolower(haystack_dup, haystack_len);
    1881                 : 
    1882               0 :         if (offset >= 0) {
    1883               0 :                 if (offset > haystack_len) {
    1884               0 :                         efree(needle_dup);
    1885               0 :                         efree(haystack_dup);
    1886               0 :                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Offset is greater than the length of haystack string");
    1887               0 :                         RETURN_FALSE;
    1888                 :                 }
    1889               0 :                 p = haystack_dup + offset;
    1890               0 :                 e = haystack_dup + haystack_len - needle_len;
    1891                 :         } else {
    1892               0 :                 if (-offset > haystack_len) {
    1893               0 :                         efree(needle_dup);
    1894               0 :                         efree(haystack_dup);
    1895               0 :                         php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Offset is greater than the length of haystack string");
    1896               0 :                         RETURN_FALSE;
    1897                 :                 }
    1898               0 :                 p = haystack_dup;
    1899               0 :                 if (needle_len > -offset) {
    1900               0 :                         e = haystack_dup + haystack_len - needle_len;
    1901                 :                 } else {
    1902               0 :                         e = haystack_dup + haystack_len + offset;
    1903                 :                 }
    1904                 :         }
    1905                 : 
    1906               0 :         while (e >= p) {
    1907               0 :                 if (memcmp(e, needle_dup, needle_len) == 0) {
    1908               0 :                         efree(haystack_dup);
    1909               0 :                         efree(needle_dup);
    1910               0 :                         RETURN_LONG(e - p + (offset > 0 ? offset : 0));
    1911                 :                 }
    1912               0 :                 e--;
    1913                 :         }
    1914                 : 
    1915               0 :         efree(haystack_dup);
    1916               0 :         efree(needle_dup);
    1917               0 :         RETURN_FALSE;
    1918                 : }
    1919                 : /* }}} */
    1920                 : 
    1921                 : /* {{{ proto string strrchr(string haystack, string needle)
    1922                 :    Finds the last occurrence of a character in a string within another */
    1923                 : PHP_FUNCTION(strrchr)
    1924               0 : {
    1925                 :         zval **haystack, **needle;
    1926               0 :         char *found = NULL;
    1927                 :         long found_offset;
    1928                 :         
    1929               0 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &haystack, &needle) ==
    1930                 :                 FAILURE) {
    1931               0 :                 WRONG_PARAM_COUNT;
    1932                 :         }
    1933               0 :         convert_to_string_ex(haystack);
    1934                 : 
    1935               0 :         if (Z_TYPE_PP(needle) == IS_STRING) {
    1936               0 :                 found = zend_memrchr(Z_STRVAL_PP(haystack), *Z_STRVAL_PP(needle), Z_STRLEN_PP(haystack));
    1937                 :         } else {
    1938               0 :                 convert_to_long_ex(needle);
    1939               0 :                 found = zend_memrchr(Z_STRVAL_PP(haystack), (char) Z_LVAL_PP(needle), Z_STRLEN_PP(haystack));
    1940                 :         }
    1941                 : 
    1942               0 :         if (found) {
    1943               0 :                 found_offset = found - Z_STRVAL_PP(haystack);
    1944               0 :                 RETURN_STRINGL(found, Z_STRLEN_PP(haystack) - found_offset, 1);
    1945                 :         } else {
    1946               0 :                 RETURN_FALSE;
    1947                 :         }
    1948                 : }
    1949                 : /* }}} */
    1950                 : 
    1951                 : /* {{{ php_chunk_split
    1952                 :  */
    1953                 : static char *php_chunk_split(char *src, int srclen, char *end, int endlen, int chunklen, int *destlen)
    1954               0 : {
    1955                 :         char *dest;
    1956                 :         char *p, *q;
    1957                 :         int chunks; /* complete chunks! */
    1958                 :         int restlen;
    1959                 : 
    1960               0 :         chunks = srclen / chunklen;
    1961               0 :         restlen = srclen - chunks * chunklen; /* srclen % chunklen */
    1962                 : 
    1963               0 :         dest = safe_emalloc((srclen + (chunks + 1) * endlen + 1), sizeof(char), 0);
    1964                 : 
    1965               0 :         for (p = src, q = dest; p < (src + srclen - chunklen + 1); ) {
    1966               0 :                 memcpy(q, p, chunklen);
    1967               0 :                 q += chunklen;
    1968               0 :                 memcpy(q, end, endlen);
    1969               0 :                 q += endlen;
    1970               0 :                 p += chunklen;
    1971                 :         }
    1972                 : 
    1973               0 :         if (restlen) {
    1974               0 :                 memcpy(q, p, restlen);
    1975               0 :                 q += restlen;
    1976               0 :                 memcpy(q, end, endlen);
    1977               0 :                 q += endlen;
    1978                 :         }
    1979                 : 
    1980               0 :         *q = '\0';
    1981               0 :         if (destlen) {
    1982               0 :                 *destlen = q - dest;
    1983                 :         }
    1984                 : 
    1985               0 :         return(dest);
    1986                 : }
    1987                 : /* }}} */
    1988                 : 
    1989                 : /* {{{ proto string chunk_split(string str [, int chunklen [, string ending]])
    1990                 :    Returns split line */
    1991                 : PHP_FUNCTION(chunk_split) 
    1992               0 : {
    1993                 :         zval **p_str, **p_chunklen, **p_ending;
    1994                 :         char *result;
    1995               0 :         char *end    = "\r\n";
    1996               0 :         int endlen   = 2;
    1997               0 :         int chunklen = 76;
    1998                 :         int result_len;
    1999               0 :         int argc = ZEND_NUM_ARGS();
    2000                 : 
    2001               0 :         if (argc < 1 || argc > 3 ||       zend_get_parameters_ex(argc, &p_str, &p_chunklen, &p_ending) == FAILURE) {
    2002               0 :                 WRONG_PARAM_COUNT;
    2003                 :         }
    2004                 : 
    2005               0 :         convert_to_string_ex(p_str);
    2006                 : 
    2007               0 :         if (argc > 1) {
    2008               0 :                 convert_to_long_ex(p_chunklen);
    2009               0 :                 chunklen = Z_LVAL_PP(p_chunklen);
    2010                 :         }
    2011                 : 
    2012               0 :         if (argc > 2) {
    2013               0 :                 convert_to_string_ex(p_ending);
    2014               0 :                 end = Z_STRVAL_PP(p_ending);
    2015               0 :                 endlen = Z_STRLEN_PP(p_ending);
    2016                 :         }
    2017                 : 
    2018               0 :         if (chunklen <= 0) {
    2019               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Chunk length should be greater than zero.");
    2020               0 :                 RETURN_FALSE;
    2021                 :         }
    2022                 : 
    2023               0 :         if (chunklen > Z_STRLEN_PP(p_str)) {
    2024                 :                 /* to maintain BC, we must return original string + ending */
    2025               0 :                 result_len = endlen + Z_STRLEN_PP(p_str);
    2026               0 :                 result = emalloc(result_len + 1);
    2027               0 :                 memcpy(result, Z_STRVAL_PP(p_str), Z_STRLEN_PP(p_str));
    2028               0 :                 memcpy(result + Z_STRLEN_PP(p_str), end, endlen);
    2029               0 :                 result[result_len] = '\0'; 
    2030               0 :                 RETURN_STRINGL(result, result_len, 0);  
    2031                 :         }
    2032                 : 
    2033               0 :         if (!Z_STRLEN_PP(p_str)) {
    2034               0 :                 RETURN_EMPTY_STRING();
    2035                 :         }
    2036                 : 
    2037               0 :         result = php_chunk_split(Z_STRVAL_PP(p_str), Z_STRLEN_PP(p_str), end, endlen, chunklen, &result_len);
    2038                 : 
    2039               0 :         if (result) {
    2040               0 :                 RETURN_STRINGL(result, result_len, 0);
    2041                 :         } else {
    2042               0 :                 RETURN_FALSE;
    2043                 :         }
    2044                 : }
    2045                 : /* }}} */
    2046                 : 
    2047                 : /* {{{ proto string substr(string str, int start [, int length])
    2048                 :    Returns part of a string */
    2049                 : PHP_FUNCTION(substr)
    2050            1607 : {
    2051                 :         zval **str, **from, **len;
    2052                 :         int l;
    2053                 :         int f;
    2054            1607 :         int argc = ZEND_NUM_ARGS();
    2055                 : 
    2056            1607 :         if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &str, &from, &len) == FAILURE) {
    2057               0 :                 WRONG_PARAM_COUNT;
    2058                 :         }
    2059                 : 
    2060            1607 :         convert_to_string_ex(str);
    2061            1607 :         convert_to_long_ex(from);
    2062                 : 
    2063            1607 :         if (argc > 2) {
    2064             175 :                 convert_to_long_ex(len);
    2065             175 :                 l = Z_LVAL_PP(len);
    2066             175 :                 if ((l < 0 && -l > Z_STRLEN_PP(str))) {
    2067               0 :                         RETURN_FALSE;
    2068             175 :                 } else if (l > Z_STRLEN_PP(str)) {
    2069               0 :                         l = Z_STRLEN_PP(str);
    2070                 :                 }
    2071                 :         } else {
    2072            1432 :                 l = Z_STRLEN_PP(str);
    2073                 :         }
    2074                 :         
    2075            1607 :         f = Z_LVAL_PP(from);
    2076            1607 :         if (f > Z_STRLEN_PP(str) || (f < 0 && -f > Z_STRLEN_PP(str))) {
    2077              73 :                 RETURN_FALSE;
    2078                 :         }
    2079                 : 
    2080            1534 :         if (l < 0 && (l + Z_STRLEN_PP(str) - f) < 0) {
    2081               0 :                 RETURN_FALSE;
    2082                 :         }
    2083                 : 
    2084                 :         /* if "from" position is negative, count start position from the end
    2085                 :          * of the string
    2086                 :          */
    2087            1534 :         if (f < 0) {
    2088            1359 :                 f = Z_STRLEN_PP(str) + f;
    2089            1359 :                 if (f < 0) {
    2090               0 :                         f = 0;
    2091                 :                 }
    2092                 :         }
    2093                 : 
    2094                 :         /* if "length" position is negative, set it to the length
    2095                 :          * needed to stop that many chars from the end of the string
    2096                 :          */
    2097            1534 :         if (l < 0) {
    2098               0 :                 l = (Z_STRLEN_PP(str) - f) + l;
    2099               0 :                 if (l < 0) {
    2100               0 :                         l = 0;
    2101                 :                 }
    2102                 :         }
    2103                 : 
    2104            1534 :         if (f >= Z_STRLEN_PP(str)) {
    2105               0 :                 RETURN_FALSE;
    2106                 :         }
    2107                 : 
    2108            1534 :         if ((f + l) > Z_STRLEN_PP(str)) {
    2109            1353 :                 l = Z_STRLEN_PP(str) - f;
    2110                 :         }
    2111                 : 
    2112            1534 :         RETURN_STRINGL(Z_STRVAL_PP(str) + f, l, 1);
    2113                 : }
    2114                 : /* }}} */
    2115                 : 
    2116                 : 
    2117                 : /* {{{ proto mixed substr_replace(mixed str, mixed repl, mixed start [, mixed length])
    2118                 :    Replaces part of a string with another string */
    2119                 : PHP_FUNCTION(substr_replace)
    2120               0 : {
    2121                 :         zval **str;
    2122                 :         zval **from;
    2123               0 :         zval **len = NULL;
    2124                 :         zval **repl;
    2125                 :         char *result;
    2126                 :         int result_len;
    2127               0 :         int l = 0;
    2128                 :         int f;
    2129               0 :         int argc = ZEND_NUM_ARGS();
    2130                 : 
    2131                 :         HashPosition pos_str, pos_from, pos_repl, pos_len;
    2132               0 :         zval **tmp_str = NULL, **tmp_from = NULL, **tmp_repl = NULL, **tmp_len= NULL;
    2133                 : 
    2134                 : 
    2135               0 :         if (argc < 3 || argc > 4 || zend_get_parameters_ex(argc, &str, &repl, &from, &len) == FAILURE) {
    2136               0 :                 WRONG_PARAM_COUNT;
    2137                 :         }
    2138                 :         
    2139               0 :         if (Z_TYPE_PP(str) != IS_ARRAY) {
    2140               0 :                 convert_to_string_ex(str);
    2141                 :         }
    2142               0 :         if (Z_TYPE_PP(repl) != IS_ARRAY) {
    2143               0 :                 convert_to_string_ex(repl);
    2144                 :         }
    2145               0 :         if (Z_TYPE_PP(from) != IS_ARRAY) {
    2146               0 :                 convert_to_long_ex(from);
    2147                 :         }
    2148                 : 
    2149               0 :         if (argc > 3) {
    2150               0 :                 if (Z_TYPE_PP(len) != IS_ARRAY) {
    2151               0 :                         convert_to_long_ex(len);
    2152               0 :                         l = Z_LVAL_PP(len);
    2153                 :                 }
    2154                 :         } else {
    2155               0 :                 if (Z_TYPE_PP(str) != IS_ARRAY) {
    2156               0 :                         l = Z_STRLEN_PP(str);
    2157                 :                 }
    2158                 :         }
    2159                 : 
    2160               0 :         if (Z_TYPE_PP(str) == IS_STRING) {
    2161               0 :                 if (
    2162                 :                         (argc == 3 && Z_TYPE_PP(from) == IS_ARRAY) 
    2163                 :                         || 
    2164                 :                         (argc == 4 && Z_TYPE_PP(from) != Z_TYPE_PP(len))
    2165                 :                 ) {
    2166               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "'from' and 'len' should be of same type - numerical or array ");
    2167               0 :                         RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);          
    2168                 :                 }
    2169               0 :                 if (argc == 4 && Z_TYPE_PP(from) == IS_ARRAY) {
    2170               0 :                         if (zend_hash_num_elements(Z_ARRVAL_PP(from)) != zend_hash_num_elements(Z_ARRVAL_PP(len))) {
    2171               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "'from' and 'len' should have the same number of elements");
    2172               0 :                                 RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);          
    2173                 :                         }
    2174                 :                 }
    2175                 :         }
    2176                 : 
    2177                 :         
    2178               0 :         if (Z_TYPE_PP(str) != IS_ARRAY) {
    2179               0 :                 if (Z_TYPE_PP(from) != IS_ARRAY) {
    2180               0 :                         int repl_len = 0;
    2181                 : 
    2182               0 :                         f = Z_LVAL_PP(from);
    2183                 : 
    2184                 :                         /* if "from" position is negative, count start position from the end
    2185                 :                          * of the string
    2186                 :                          */
    2187               0 :                         if (f < 0) {
    2188               0 :                                 f = Z_STRLEN_PP(str) + f;
    2189               0 :                                 if (f < 0) {
    2190               0 :                                         f = 0;
    2191                 :                                 }
    2192               0 :                         } else if (f > Z_STRLEN_PP(str)) {
    2193               0 :                                 f = Z_STRLEN_PP(str);
    2194                 :                         }
    2195                 :                         /* if "length" position is negative, set it to the length
    2196                 :                          * needed to stop that many chars from the end of the string
    2197                 :                          */
    2198               0 :                         if (l < 0) {
    2199               0 :                                 l = (Z_STRLEN_PP(str) - f) + l;
    2200               0 :                                 if (l < 0) {
    2201               0 :                                         l = 0;
    2202                 :                                 }
    2203                 :                         }
    2204                 : 
    2205               0 :                         if (f > Z_STRLEN_PP(str) || (f < 0 && -f > Z_STRLEN_PP(str))) {
    2206               0 :                                 RETURN_FALSE;
    2207               0 :                         } else if (l > Z_STRLEN_PP(str) || (l < 0 && -l > Z_STRLEN_PP(str))) {
    2208               0 :                                 RETURN_FALSE;
    2209                 :                         }
    2210                 : 
    2211               0 :                         if ((f + l) > Z_STRLEN_PP(str)) {
    2212               0 :                                 l = Z_STRLEN_PP(str) - f;
    2213                 :                         }
    2214               0 :                         if (Z_TYPE_PP(repl) == IS_ARRAY) {
    2215               0 :                                 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(repl), &pos_repl);
    2216               0 :                                 if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(repl), (void **) &tmp_repl, &pos_repl)) {
    2217               0 :                                         convert_to_string_ex(tmp_repl);
    2218               0 :                                         repl_len = Z_STRLEN_PP(tmp_repl);
    2219                 :                                 }
    2220                 :                         } else {
    2221               0 :                                 repl_len = Z_STRLEN_PP(repl);
    2222                 :                         }
    2223               0 :                         result_len = Z_STRLEN_PP(str) - l + repl_len;
    2224               0 :                         result = emalloc(result_len + 1);
    2225                 : 
    2226               0 :                         memcpy(result, Z_STRVAL_PP(str), f);
    2227               0 :                         if (repl_len) {
    2228               0 :                                 memcpy((result + f), (Z_TYPE_PP(repl) == IS_ARRAY ? Z_STRVAL_PP(tmp_repl) : Z_STRVAL_PP(repl)), repl_len);
    2229                 :                         }
    2230               0 :                         memcpy((result + f + repl_len), Z_STRVAL_PP(str) + f + l, Z_STRLEN_PP(str) - f - l);
    2231               0 :                         result[result_len] = '\0';
    2232               0 :                         RETURN_STRINGL(result, result_len, 0);
    2233                 :                 } else {
    2234               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Functionality of 'from' and 'len' as arrays is not implemented.");
    2235               0 :                         RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);  
    2236                 :                 }
    2237                 :         } else { /* str is array of strings */
    2238               0 :                 array_init(return_value);
    2239                 : 
    2240               0 :                 if (Z_TYPE_PP(from) == IS_ARRAY) {
    2241               0 :                         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(from), &pos_from);
    2242                 :                 }
    2243                 : 
    2244               0 :                 if (argc > 3 && Z_TYPE_PP(len) == IS_ARRAY) {
    2245               0 :                         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(len), &pos_len);
    2246                 :                 }
    2247                 : 
    2248               0 :                 if (Z_TYPE_PP(repl) == IS_ARRAY) {
    2249               0 :                         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(repl), &pos_repl);
    2250                 :                 }
    2251                 : 
    2252               0 :                 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(str), &pos_str);
    2253               0 :                 while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(str), (void **) &tmp_str, &pos_str) == SUCCESS) {
    2254               0 :                         convert_to_string_ex(tmp_str);
    2255                 : 
    2256               0 :                         if (Z_TYPE_PP(from) == IS_ARRAY) {
    2257               0 :                                 if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(from), (void **) &tmp_from, &pos_from)) {
    2258               0 :                                         convert_to_long_ex(tmp_from);
    2259                 : 
    2260               0 :                                         f = Z_LVAL_PP(tmp_from);
    2261               0 :                                         if (f < 0) {
    2262               0 :                                                 f = Z_STRLEN_PP(tmp_str) + f;
    2263               0 :                                                 if (f < 0) {
    2264               0 :                                                         f = 0;
    2265                 :                                                 }
    2266               0 :                                         } else if (f > Z_STRLEN_PP(tmp_str)) {
    2267               0 :                                                 f = Z_STRLEN_PP(tmp_str);
    2268                 :                                         }
    2269               0 :                                         zend_hash_move_forward_ex(Z_ARRVAL_PP(from), &pos_from);
    2270                 :                                 } else {
    2271               0 :                                         f = 0;
    2272                 :                                 }
    2273                 :                         } else {
    2274               0 :                                 f = Z_LVAL_PP(from);
    2275               0 :                                 if (f < 0) {
    2276               0 :                                         f = Z_STRLEN_PP(tmp_str) + f;
    2277               0 :                                         if (f < 0) {
    2278               0 :                                                 f = 0;
    2279                 :                                         }
    2280               0 :                                 } else if (f > Z_STRLEN_PP(tmp_str)) {
    2281               0 :                                         f = Z_STRLEN_PP(tmp_str);
    2282                 :                                 }
    2283                 :                         }
    2284                 : 
    2285               0 :                         if (argc > 3 && Z_TYPE_PP(len) == IS_ARRAY) {
    2286               0 :                                 if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(len), (void **) &tmp_len, &pos_len)) {
    2287               0 :                                         convert_to_long_ex(tmp_len);
    2288                 : 
    2289               0 :                                         l = Z_LVAL_PP(tmp_len);
    2290               0 :                                         zend_hash_move_forward_ex(Z_ARRVAL_PP(len), &pos_len);
    2291                 :                                 } else {
    2292               0 :                                         l = Z_STRLEN_PP(tmp_str);
    2293                 :                                 }
    2294               0 :                         } else if (argc > 3) { 
    2295               0 :                                 l = Z_LVAL_PP(len);
    2296                 :                         } else {
    2297               0 :                                 l = Z_STRLEN_PP(tmp_str);
    2298                 :                         }
    2299                 : 
    2300               0 :                         if (l < 0) {
    2301               0 :                                 l = (Z_STRLEN_PP(tmp_str) - f) + l;
    2302               0 :                                 if (l < 0) {
    2303               0 :                                         l = 0;
    2304                 :                                 }
    2305                 :                         }
    2306                 : 
    2307               0 :                         if ((f + l) > Z_STRLEN_PP(tmp_str)) {
    2308               0 :                                 l = Z_STRLEN_PP(tmp_str) - f;
    2309                 :                         }
    2310                 : 
    2311               0 :                         result_len = Z_STRLEN_PP(tmp_str) - l;
    2312                 : 
    2313               0 :                         if (Z_TYPE_PP(repl) == IS_ARRAY) {
    2314               0 :                                 if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(repl), (void **) &tmp_repl, &pos_repl)) {
    2315               0 :                                         convert_to_string_ex(tmp_repl);
    2316               0 :                                         result_len += Z_STRLEN_PP(tmp_repl);
    2317               0 :                                         zend_hash_move_forward_ex(Z_ARRVAL_PP(repl), &pos_repl);    
    2318               0 :                                         result = emalloc(result_len + 1);
    2319                 : 
    2320               0 :                                         memcpy(result, Z_STRVAL_PP(tmp_str), f);
    2321               0 :                                         memcpy((result + f), Z_STRVAL_PP(tmp_repl), Z_STRLEN_PP(tmp_repl));
    2322               0 :                                         memcpy((result + f + Z_STRLEN_PP(tmp_repl)), Z_STRVAL_PP(tmp_str) + f + l, Z_STRLEN_PP(tmp_str) - f - l);
    2323                 :                                 } else {
    2324               0 :                                         result = emalloc(result_len + 1);
    2325                 :         
    2326               0 :                                         memcpy(result, Z_STRVAL_PP(tmp_str), f);
    2327               0 :                                         memcpy((result + f), Z_STRVAL_PP(tmp_str) + f + l, Z_STRLEN_PP(tmp_str) - f - l);
    2328                 :                                 }
    2329                 :                         } else {
    2330               0 :                                 result_len += Z_STRLEN_PP(repl);
    2331                 : 
    2332               0 :                                 result = emalloc(result_len + 1);
    2333                 : 
    2334               0 :                                 memcpy(result, Z_STRVAL_PP(tmp_str), f);
    2335               0 :                                 memcpy((result + f), Z_STRVAL_PP(repl), Z_STRLEN_PP(repl));
    2336               0 :                                 memcpy((result + f + Z_STRLEN_PP(repl)), Z_STRVAL_PP(tmp_str) + f + l, Z_STRLEN_PP(tmp_str) - f - l);
    2337                 :                         }
    2338                 : 
    2339               0 :                         result[result_len] = '\0';
    2340               0 :                         add_next_index_stringl(return_value, result, result_len, 0);
    2341                 : 
    2342               0 :                         zend_hash_move_forward_ex(Z_ARRVAL_PP(str), &pos_str);
    2343                 :                 } /*while*/
    2344                 :         } /* if */
    2345                 : }
    2346                 : /* }}} */
    2347                 : 
    2348                 : 
    2349                 : 
    2350                 : 
    2351                 : /* {{{ proto string quotemeta(string str)
    2352                 :    Quotes meta characters */
    2353                 : PHP_FUNCTION(quotemeta)
    2354               0 : {
    2355                 :         zval **arg;
    2356                 :         char *str, *old;
    2357                 :         char *old_end;
    2358                 :         char *p, *q;
    2359                 :         char c;
    2360                 :         
    2361               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
    2362               0 :                 WRONG_PARAM_COUNT;
    2363                 :         }
    2364                 : 
    2365               0 :         convert_to_string_ex(arg);
    2366                 : 
    2367               0 :         old = Z_STRVAL_PP(arg);
    2368               0 :         old_end = Z_STRVAL_PP(arg) + Z_STRLEN_PP(arg);
    2369                 : 
    2370               0 :         if (old == old_end) {
    2371               0 :                 RETURN_FALSE;
    2372                 :         }
    2373                 :         
    2374               0 :         str = safe_emalloc(2, Z_STRLEN_PP(arg), 1);
    2375                 :         
    2376               0 :         for (p = old, q = str; p != old_end; p++) {
    2377               0 :                 c = *p;
    2378               0 :                 switch (c) {
    2379                 :                         case '.':
    2380                 :                         case '\\':
    2381                 :                         case '+':
    2382                 :                         case '*':
    2383                 :                         case '?':
    2384                 :                         case '[':
    2385                 :                         case '^':
    2386                 :                         case ']':
    2387                 :                         case '$':
    2388                 :                         case '(':
    2389                 :                         case ')':
    2390               0 :                                 *q++ = '\\';
    2391                 :                                 /* break is missing _intentionally_ */
    2392                 :                         default:
    2393               0 :                                 *q++ = c;
    2394                 :                 }
    2395                 :         }
    2396               0 :         *q = 0;
    2397                 : 
    2398               0 :         RETURN_STRINGL(erealloc(str, q - str + 1), q - str, 0);
    2399                 : }
    2400                 : /* }}} */
    2401                 : 
    2402                 : /* {{{ proto int ord(string character)
    2403                 :    Returns ASCII value of character */
    2404                 : PHP_FUNCTION(ord)
    2405               0 : {
    2406                 :         zval **str;
    2407                 :         
    2408               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {
    2409               0 :                 WRONG_PARAM_COUNT;
    2410                 :         }
    2411               0 :         convert_to_string_ex(str);
    2412                 : 
    2413               0 :         RETURN_LONG((unsigned char) Z_STRVAL_PP(str)[0]);
    2414                 : }
    2415                 : /* }}} */
    2416                 : 
    2417                 : /* {{{ proto string chr(int ascii)
    2418                 :    Converts ASCII code to a character */
    2419                 : PHP_FUNCTION(chr)
    2420            5000 : {
    2421                 :         zval **num;
    2422                 :         char temp[2];
    2423                 :         
    2424            5000 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &num) == FAILURE) {
    2425               0 :                 WRONG_PARAM_COUNT;
    2426                 :         }
    2427            5000 :         convert_to_long_ex(num);
    2428                 :         
    2429            5000 :         temp[0] = (char) Z_LVAL_PP(num);
    2430            5000 :         temp[1] = 0;
    2431                 : 
    2432            5000 :         RETVAL_STRINGL(temp, 1, 1);
    2433                 : }
    2434                 : /* }}} */
    2435                 : 
    2436                 : /* {{{ proto string ucfirst(string str)
    2437                 :    Makes a string's first character uppercase */
    2438                 : PHP_FUNCTION(ucfirst)
    2439               0 : {
    2440                 :         zval **str;
    2441                 :         
    2442               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {
    2443               0 :                 WRONG_PARAM_COUNT;
    2444                 :         }
    2445               0 :         convert_to_string_ex(str);
    2446                 : 
    2447               0 :         if (!Z_STRLEN_PP(str)) {
    2448               0 :                 RETURN_EMPTY_STRING();
    2449                 :         }
    2450                 : 
    2451               0 :         ZVAL_STRINGL(return_value, Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
    2452               0 :         *Z_STRVAL_P(return_value) = toupper((unsigned char) *Z_STRVAL_P(return_value));
    2453                 : }
    2454                 : /* }}} */
    2455                 : 
    2456                 : /* {{{ proto string ucwords(string str)
    2457                 :    Uppercase the first character of every word in a string */
    2458                 : PHP_FUNCTION(ucwords)
    2459               0 : {
    2460                 :         zval **str;
    2461                 :         register char *r, *r_end;
    2462                 :         
    2463               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {
    2464               0 :                 WRONG_PARAM_COUNT;
    2465                 :         }
    2466               0 :         convert_to_string_ex(str);
    2467                 : 
    2468               0 :         if (!Z_STRLEN_PP(str)) {
    2469               0 :                 RETURN_EMPTY_STRING();
    2470                 :         }
    2471                 : 
    2472               0 :         ZVAL_STRINGL(return_value, Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
    2473               0 :         r = Z_STRVAL_P(return_value);
    2474                 : 
    2475               0 :         *r = toupper((unsigned char) *r);
    2476               0 :         for (r_end = r + Z_STRLEN_P(return_value) - 1; r < r_end; ) {
    2477               0 :                 if (isspace((int) *(unsigned char *)r++)) {
    2478               0 :                         *r = toupper((unsigned char) *r);
    2479                 :                 }
    2480                 :         }
    2481                 : }
    2482                 : /* }}} */
    2483                 : 
    2484                 : /* {{{ php_strtr
    2485                 :  */
    2486                 : PHPAPI char *php_strtr(char *str, int len, char *str_from, char *str_to, int trlen)
    2487               0 : {
    2488                 :         int i;
    2489                 :         unsigned char xlat[256];
    2490                 : 
    2491               0 :         if ((trlen < 1) || (len < 1)) {
    2492               0 :                 return str;
    2493                 :         }
    2494                 : 
    2495               0 :         for (i = 0; i < 256; xlat[i] = i, i++);
    2496                 : 
    2497               0 :         for (i = 0; i < trlen; i++) {
    2498               0 :                 xlat[(unsigned char) str_from[i]] = str_to[i];
    2499                 :         }
    2500                 : 
    2501               0 :         for (i = 0; i < len; i++) {
    2502               0 :                 str[i] = xlat[(unsigned char) str[i]];
    2503                 :         }
    2504                 : 
    2505               0 :         return str;
    2506                 : }
    2507                 : /* }}} */
    2508                 : 
    2509                 : /* {{{ php_strtr_array
    2510                 :  */
    2511                 : static void php_strtr_array(zval *return_value, char *str, int slen, HashTable *hash)
    2512               0 : {
    2513                 :         zval **entry;
    2514                 :         char  *string_key;
    2515                 :         uint   string_key_len;
    2516                 :         zval **trans;
    2517                 :         zval   ctmp;
    2518                 :         ulong num_key;
    2519               0 :         int minlen = 128*1024;
    2520               0 :         int maxlen = 0, pos, len, found;
    2521                 :         char *key;
    2522                 :         HashPosition hpos;
    2523               0 :         smart_str result = {0};
    2524                 :         HashTable tmp_hash;
    2525                 :         
    2526               0 :         zend_hash_init(&tmp_hash, zend_hash_num_elements(hash), NULL, NULL, 0);
    2527               0 :         zend_hash_internal_pointer_reset_ex(hash, &hpos);
    2528               0 :         while (zend_hash_get_current_data_ex(hash, (void **)&entry, &hpos) == SUCCESS) {
    2529               0 :                 switch (zend_hash_get_current_key_ex(hash, &string_key, &string_key_len, &num_key, 0, &hpos)) {
    2530                 :                         case HASH_KEY_IS_STRING:
    2531               0 :                                 len = string_key_len-1;
    2532               0 :                                 if (len < 1) {
    2533               0 :                                         zend_hash_destroy(&tmp_hash);
    2534               0 :                                         RETURN_FALSE;
    2535                 :                                 }
    2536               0 :                                 zend_hash_add(&tmp_hash, string_key, string_key_len, entry, sizeof(zval*), NULL);
    2537               0 :                                 if (len > maxlen) {
    2538               0 :                                         maxlen = len;
    2539                 :                                 }
    2540               0 :                                 if (len < minlen) {
    2541               0 :                                         minlen = len;
    2542                 :                                 }
    2543               0 :                                 break; 
    2544                 :                         
    2545                 :                         case HASH_KEY_IS_LONG:
    2546               0 :                                 Z_TYPE(ctmp) = IS_LONG;
    2547               0 :                                 Z_LVAL(ctmp) = num_key;
    2548                 :                         
    2549               0 :                                 convert_to_string(&ctmp);
    2550               0 :                                 len = Z_STRLEN(ctmp);
    2551               0 :                                 zend_hash_add(&tmp_hash, Z_STRVAL(ctmp), len+1, entry, sizeof(zval*), NULL);
    2552               0 :                                 zval_dtor(&ctmp);
    2553                 : 
    2554               0 :                                 if (len > maxlen) {
    2555               0 :                                         maxlen = len;
    2556                 :                                 }
    2557               0 :                                 if (len < minlen) {
    2558               0 :                                         minlen = len;
    2559                 :                                 }
    2560                 :                                 break;
    2561                 :                 }
    2562               0 :                 zend_hash_move_forward_ex(hash, &hpos);
    2563                 :         }
    2564                 : 
    2565               0 :         key = emalloc(maxlen+1);
    2566               0 :         pos = 0;
    2567                 : 
    2568               0 :         while (pos < slen) {
    2569               0 :                 if ((pos + maxlen) > slen) {
    2570               0 :                         maxlen = slen - pos;
    2571                 :                 }
    2572                 : 
    2573               0 :                 found = 0;
    2574               0 :                 memcpy(key, str+pos, maxlen);
    2575                 : 
    2576               0 :                 for (len = maxlen; len >= minlen; len--) {
    2577               0 :                         key[len] = 0;
    2578                 :                         
    2579               0 :                         if (zend_hash_find(&tmp_hash, key, len+1, (void**)&trans) == SUCCESS) {
    2580                 :                                 char *tval;
    2581                 :                                 int tlen;
    2582                 :                                 zval tmp;
    2583                 : 
    2584               0 :                                 if (Z_TYPE_PP(trans) != IS_STRING) {
    2585               0 :                                         tmp = **trans;
    2586               0 :                                         zval_copy_ctor(&tmp);
    2587               0 :                                         convert_to_string(&tmp);
    2588               0 :                                         tval = Z_STRVAL(tmp);
    2589               0 :                                         tlen = Z_STRLEN(tmp);
    2590                 :                                 } else {
    2591               0 :                                         tval = Z_STRVAL_PP(trans);
    2592               0 :                                         tlen = Z_STRLEN_PP(trans);
    2593                 :                                 }
    2594                 : 
    2595               0 :                                 smart_str_appendl(&result, tval, tlen);
    2596               0 :                                 pos += len;
    2597               0 :                                 found = 1;
    2598                 : 
    2599               0 :                                 if (Z_TYPE_PP(trans) != IS_STRING) {
    2600               0 :                                         zval_dtor(&tmp);
    2601                 :                                 }
    2602               0 :                                 break;
    2603                 :                         } 
    2604                 :                 }
    2605                 : 
    2606               0 :                 if (! found) {
    2607               0 :                         smart_str_appendc(&result, str[pos++]);
    2608                 :                 }
    2609                 :         }
    2610                 : 
    2611               0 :         efree(key);
    2612               0 :         zend_hash_destroy(&tmp_hash);
    2613               0 :         smart_str_0(&result);
    2614               0 :         RETVAL_STRINGL(result.c, result.len, 0);
    2615                 : }
    2616                 : /* }}} */
    2617                 : 
    2618                 : /* {{{ proto string strtr(string str, string from[, string to])
    2619                 :    Translates characters in str using given translation tables */
    2620                 : PHP_FUNCTION(strtr)
    2621               0 : {                                                               
    2622                 :         zval **str, **from, **to;
    2623               0 :         int ac = ZEND_NUM_ARGS();
    2624                 : 
    2625               0 :         if (ac < 2 || ac > 3 || zend_get_parameters_ex(ac, &str, &from, &to) == FAILURE) {
    2626               0 :                 WRONG_PARAM_COUNT;
    2627                 :         }
    2628                 :         
    2629               0 :         if (ac == 2 && Z_TYPE_PP(from) != IS_ARRAY) {
    2630               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The second argument is not an array.");
    2631               0 :                 RETURN_FALSE;
    2632                 :         }
    2633                 : 
    2634               0 :         convert_to_string_ex(str);
    2635                 : 
    2636                 :         /* shortcut for empty string */
    2637               0 :         if (Z_STRLEN_PP(str) == 0) {
    2638               0 :                 RETURN_EMPTY_STRING();
    2639                 :         }
    2640                 : 
    2641               0 :         if (ac == 2) {
    2642               0 :                 php_strtr_array(return_value, Z_STRVAL_PP(str), Z_STRLEN_PP(str), HASH_OF(*from));
    2643                 :         } else {
    2644               0 :                 convert_to_string_ex(from);
    2645               0 :                 convert_to_string_ex(to);
    2646                 : 
    2647               0 :                 ZVAL_STRINGL(return_value, Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
    2648                 :                 
    2649               0 :                 php_strtr(Z_STRVAL_P(return_value),
    2650                 :                                   Z_STRLEN_P(return_value),
    2651                 :                                   Z_STRVAL_PP(from),
    2652                 :                                   Z_STRVAL_PP(to),
    2653                 :                                   MIN(Z_STRLEN_PP(from), 
    2654                 :                                   Z_STRLEN_PP(to)));
    2655                 :         }
    2656                 : }
    2657                 : /* }}} */
    2658                 : 
    2659                 : /* {{{ proto string strrev(string str)
    2660                 :    Reverse a string */
    2661                 : PHP_FUNCTION(strrev)
    2662               0 : {
    2663                 :         zval **str;
    2664                 :         char *s, *e, *n, *p;
    2665                 :         
    2666               0 :         if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &str) == FAILURE) {
    2667               0 :                 WRONG_PARAM_COUNT;
    2668                 :         }
    2669               0 :         convert_to_string_ex(str);
    2670                 :         
    2671               0 :         n = emalloc(Z_STRLEN_PP(str)+1);
    2672               0 :         p = n;
    2673                 :         
    2674               0 :         s = Z_STRVAL_PP(str);
    2675               0 :         e = s + Z_STRLEN_PP(str);
    2676                 :         
    2677               0 :         while (--e>=s) {
    2678               0 :                 *p++ = *e;
    2679                 :         }
    2680                 :         
    2681               0 :         *p = '\0';
    2682                 :         
    2683               0 :         RETVAL_STRINGL(n, Z_STRLEN_PP(str), 0);
    2684                 : }
    2685                 : /* }}} */
    2686                 : 
    2687                 : /* {{{ php_similar_str
    2688                 :  */
    2689                 : static void php_similar_str(const char *txt1, int len1, const char *txt2, int len2, int *pos1, int *pos2, int *max)
    2690               0 : {
    2691                 :         char *p, *q;
    2692               0 :         char *end1 = (char *) txt1 + len1;
    2693               0 :         char *end2 = (char *) txt2 + len2;
    2694                 :         int l;
    2695                 :         
    2696               0 :         *max = 0;
    2697               0 :         for (p = (char *) txt1; p < end1; p++) {
    2698               0 :                 for (q = (char *) txt2; q < end2; q++) {
    2699               0 :                         for (l = 0; (p + l < end1) && (q + l < end2) && (p[l] == q[l]); l++);
    2700               0 :                         if (l > *max) {
    2701               0 :                                 *max = l;
    2702               0 :                                 *pos1 = p - txt1;
    2703               0 :                                 *pos2 = q - txt2;
    2704                 :                         }
    2705                 :                 }
    2706                 :         }
    2707               0 : }
    2708                 : /* }}} */
    2709                 : 
    2710                 : /* {{{ php_similar_char
    2711                 :  */
    2712                 : static int php_similar_char(const char *txt1, int len1, const char *txt2, int len2)
    2713               0 : {
    2714                 :         int sum;
    2715                 :         int pos1, pos2, max;
    2716                 : 
    2717               0 :         php_similar_str(txt1, len1, txt2, len2, &pos1, &pos2, &max);
    2718               0 :         if ((sum = max)) {
    2719               0 :                 if (pos1 && pos2) {
    2720               0 :                         sum += php_similar_char(txt1, pos1, 
    2721                 :                                                                         txt2, pos2);
    2722                 :                 }
    2723               0 :                 if ((pos1 + max < len1) && (pos2 + max < len2)) {
    2724               0 :                         sum += php_similar_char(txt1 + pos1 + max, len1 - pos1 - max, 
    2725                 :                                                                         txt2 + pos2 + max, len2 - pos2 - max);
    2726                 :                 }
    2727                 :         }
    2728                 : 
    2729               0 :         return sum;
    2730                 : }
    2731                 : /* }}} */
    2732                 : 
    2733                 : /* {{{ proto int similar_text(string str1, string str2 [, float percent])
    2734                 :    Calculates the similarity between two strings */
    2735                 : PHP_FUNCTION(similar_text)
    2736               0 : {
    2737                 :         zval **t1, **t2, **percent;
    2738               0 :         int ac = ZEND_NUM_ARGS();
    2739                 :         int sim;
    2740                 :         
    2741               0 :         if (ac < 2 || ac > 3 || zend_get_parameters_ex(ac, &t1, &t2, &percent) == FAILURE) {
    2742               0 :                 WRONG_PARAM_COUNT;
    2743                 :         }       
    2744                 : 
    2745               0 :         convert_to_string_ex(t1);
    2746               0 :         convert_to_string_ex(t2);
    2747                 : 
    2748               0 :         if (ac > 2) {
    2749               0 :                 convert_to_double_ex(percent);
    2750                 :         }
    2751                 :         
    2752               0 :         if (Z_STRLEN_PP(t1) + Z_STRLEN_PP(t2) == 0) {
    2753               0 :                 if (ac > 2) {
    2754               0 :                         Z_DVAL_PP(percent) = 0;
    2755                 :                 }
    2756                 : 
    2757               0 :                 RETURN_LONG(0);
    2758                 :         }
    2759                 :         
    2760               0 :         sim = php_similar_char(Z_STRVAL_PP(t1), Z_STRLEN_PP(t1), Z_STRVAL_PP(t2), Z_STRLEN_PP(t2));     
    2761                 : 
    2762               0 :         if (ac > 2) {
    2763               0 :                 Z_DVAL_PP(percent) = sim * 200.0 / (Z_STRLEN_PP(t1) + Z_STRLEN_PP(t2));
    2764                 :         }
    2765                 : 
    2766               0 :         RETURN_LONG(sim);
    2767                 : }
    2768                 : /* }}} */
    2769                 : 
    2770                 : /* {{{ php_stripslashes
    2771                 :  *
    2772                 :  * be careful, this edits the string in-place */
    2773                 : PHPAPI void php_stripslashes(char *str, int *len TSRMLS_DC)
    2774               0 : {
    2775                 :         char *s, *t;
    2776                 :         int l;
    2777                 : 
    2778               0 :         if (len != NULL) {
    2779               0 :                 l = *len;
    2780                 :         } else {
    2781               0 :                 l = strlen(str);
    2782                 :         }
    2783               0 :         s = str;
    2784               0 :         t = str;
    2785                 : 
    2786               0 :         if (PG(magic_quotes_sybase)) {
    2787               0 :                 while (l > 0) {
    2788               0 :                         if (*t == '\'') {
    2789               0 :                                 if ((l > 0) && (t[1] == '\'')) {
    2790               0 :                                         t++;
    2791               0 :                                         if (len != NULL) {
    2792               0 :                                                 (*len)--;
    2793                 :                                         }
    2794               0 :                                         l--;
    2795                 :                                 }
    2796               0 :                                 *s++ = *t++;
    2797               0 :                         } else if (*t == '\\' && t[1] == '0' && l > 0) {
    2798               0 :                                 *s++='\0';
    2799               0 :                                 t+=2;
    2800               0 :                                 if (len != NULL) {
    2801               0 :                                         (*len)--;
    2802                 :                                 }
    2803               0 :                                 l--;
    2804                 :                         } else {
    2805               0 :                                 *s++ = *t++;
    2806                 :                         }
    2807               0 :                         l--;
    2808                 :                 }
    2809               0 :                 *s = '\0';
    2810                 :                 
    2811               0 :                 return;
    2812                 :         }
    2813                 : 
    2814               0 :         while (l > 0) {
    2815               0 :                 if (*t == '\\') {
    2816               0 :                         t++;                            /* skip the slash */
    2817               0 :                         if (len != NULL) {
    2818               0 :                                 (*len)--;
    2819                 :                         }
    2820               0 :                         l--;
    2821               0 :                         if (l > 0) {
    2822               0 :                                 if (*t == '0') {
    2823               0 :                                         *s++='\0';
    2824               0 :                                         t++;
    2825                 :                                 } else {
    2826               0 :                                         *s++ = *t++;    /* preserve the next character */
    2827                 :                                 }
    2828               0 :                                 l--;
    2829                 :                         }
    2830                 :                 } else {
    2831               0 :                         *s++ = *t++;
    2832               0 :                         l--;
    2833                 :                 }
    2834                 :         }
    2835               0 :         if (s != t) {
    2836               0 :                 *s = '\0';
    2837                 :         }
    2838                 : }
    2839                 : /* }}} */
    2840                 : 
    2841                 : /* {{{ proto string addcslashes(string str, string charlist)
    2842                 :    Escapes all chars mentioned in charlist with backslash. It creates octal representations if asked to backslash characters with 8th bit set or with ASCII<32 (except '\n', '\r', '\t' etc...) */
    2843                 : PHP_FUNCTION(addcslashes)
    2844               0 : {
    2845                 :         zval **str, **what;
    2846                 : 
    2847               0 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &str, &what) == FAILURE) {
    2848               0 :                 WRONG_PARAM_COUNT;
    2849                 :         }
    2850               0 :         convert_to_string_ex(str);
    2851               0 :         convert_to_string_ex(what);
    2852                 : 
    2853               0 :         if (Z_STRLEN_PP(str) == 0) {
    2854               0 :                 RETURN_EMPTY_STRING();
    2855                 :         }
    2856                 : 
    2857               0 :         if (Z_STRLEN_PP(what) == 0) {
    2858               0 :                 RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
    2859                 :         }
    2860                 : 
    2861               0 :         Z_STRVAL_P(return_value) = php_addcslashes(Z_STRVAL_PP(str), Z_STRLEN_PP(str), &Z_STRLEN_P(return_value), 0, Z_STRVAL_PP(what), Z_STRLEN_PP(what) TSRMLS_CC);
    2862               0 :         RETURN_STRINGL(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value), 0);
    2863                 : }
    2864                 : /* }}} */
    2865                 : 
    2866                 : /* {{{ proto string addslashes(string str)
    2867                 :    Escapes single quote, double quotes and backslash characters in a string with backslashes */
    2868                 : PHP_FUNCTION(addslashes)
    2869            2201 : {
    2870                 :         zval **str;
    2871                 : 
    2872            2201 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {
    2873               0 :                 WRONG_PARAM_COUNT;
    2874                 :         }
    2875            2201 :         convert_to_string_ex(str);
    2876                 : 
    2877            2201 :         if (Z_STRLEN_PP(str) == 0) {
    2878             880 :                 RETURN_EMPTY_STRING();
    2879                 :         }
    2880                 : 
    2881            1321 :         RETURN_STRING(php_addslashes(Z_STRVAL_PP(str),
    2882                 :                                      Z_STRLEN_PP(str), 
    2883                 :                                      &Z_STRLEN_P(return_value), 0 
    2884                 :                                      TSRMLS_CC), 0);
    2885                 : }
    2886                 : /* }}} */
    2887                 : 
    2888                 : /* {{{ proto string stripcslashes(string str)
    2889                 :    Strips backslashes from a string. Uses C-style conventions */
    2890                 : PHP_FUNCTION(stripcslashes)
    2891               0 : {
    2892                 :         zval **str;
    2893                 :         
    2894               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {
    2895               0 :                 WRONG_PARAM_COUNT;
    2896                 :         }
    2897               0 :         convert_to_string_ex(str);
    2898                 : 
    2899               0 :         ZVAL_STRINGL(return_value, Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
    2900               0 :         php_stripcslashes(Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value));
    2901                 : }
    2902                 : /* }}} */
    2903                 : 
    2904                 : /* {{{ proto string stripslashes(string str)
    2905                 :    Strips backslashes from a string */
    2906                 : PHP_FUNCTION(stripslashes)
    2907               0 : {
    2908                 :         zval **str;
    2909                 :         
    2910               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {
    2911               0 :                 WRONG_PARAM_COUNT;
    2912                 :         }
    2913               0 :         convert_to_string_ex(str);
    2914                 : 
    2915               0 :         ZVAL_STRINGL(return_value, Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);
    2916               0 :         php_stripslashes(Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value) TSRMLS_CC);
    2917                 : }
    2918                 : /* }}} */
    2919                 : 
    2920                 : #ifndef HAVE_STRERROR
    2921                 : /* {{{ php_strerror
    2922                 :  */
    2923                 : char *php_strerror(int errnum) 
    2924                 : {
    2925                 :         extern int sys_nerr;
    2926                 :         extern char *sys_errlist[];
    2927                 :         TSRMLS_FETCH();
    2928                 : 
    2929                 :         if ((unsigned int) errnum < sys_nerr) {
    2930                 :                 return(sys_errlist[errnum]);
    2931                 :         }
    2932                 : 
    2933                 :         (void) snprintf(BG(str_ebuf), sizeof(php_basic_globals.str_ebuf), "Unknown error: %d", errnum);
    2934                 :         return(BG(str_ebuf));
    2935                 : }
    2936                 : /* }}} */
    2937                 : #endif
    2938                 : 
    2939                 : /* {{{ php_stripcslashes
    2940                 :  */
    2941                 : PHPAPI void php_stripcslashes(char *str, int *len)
    2942               0 : {
    2943                 :         char *source, *target, *end;
    2944               0 :         int  nlen = *len, i;
    2945                 :         char numtmp[4];
    2946                 : 
    2947               0 :         for (source=str, end=str+nlen, target=str; source < end; source++) {
    2948               0 :                 if (*source == '\\' && source+1 < end) {
    2949               0 :                         source++;
    2950               0 :                         switch (*source) {
    2951               0 :                                 case 'n':  *target++='\n'; nlen--; break;
    2952               0 :                                 case 'r':  *target++='\r'; nlen--; break;
    2953               0 :                                 case 'a':  *target++='\a'; nlen--; break;
    2954               0 :                                 case 't':  *target++='\t'; nlen--; break;
    2955               0 :                                 case 'v':  *target++='\v'; nlen--; break;
    2956               0 :                                 case 'b':  *target++='\b'; nlen--; break;
    2957               0 :                                 case 'f':  *target++='\f'; nlen--; break;
    2958               0 :                                 case '\\': *target++='\\'; nlen--; break;
    2959                 :                                 case 'x':
    2960               0 :                                         if (source+1 < end && isxdigit((int)(*(source+1)))) {
    2961               0 :                                                 numtmp[0] = *++source;
    2962               0 :                                                 if (source+1 < end && isxdigit((int)(*(source+1)))) {
    2963               0 :                                                         numtmp[1] = *++source;
    2964               0 :                                                         numtmp[2] = '\0';
    2965               0 :                                                         nlen-=3;
    2966                 :                                                 } else {
    2967               0 :                                                         numtmp[1] = '\0';
    2968               0 :                                                         nlen-=2;
    2969                 :                                                 }
    2970               0 :                                                 *target++=(char)strtol(numtmp, NULL, 16);
    2971               0 :                                                 break;
    2972                 :                                         }
    2973                 :                                         /* break is left intentionally */
    2974                 :                                 default: 
    2975               0 :                                         i=0; 
    2976               0 :                                         while (source < end && *source >= '0' && *source <= '7' && i<3) {
    2977               0 :                                                 numtmp[i++] = *source++;
    2978                 :                                         }
    2979               0 :                                         if (i) {
    2980               0 :                                                 numtmp[i]='\0';
    2981               0 :                                                 *target++=(char)strtol(numtmp, NULL, 8);
    2982               0 :                                                 nlen-=i;
    2983               0 :                                                 source--;
    2984                 :                                         } else {
    2985               0 :                                                 *target++=*source;
    2986               0 :                                                 nlen--;
    2987                 :                                         }
    2988                 :                         }
    2989                 :                 } else {
    2990               0 :                         *target++=*source;
    2991                 :                 }
    2992                 :         }
    2993                 : 
    2994               0 :         if (nlen != 0) {
    2995               0 :                 *target='\0';
    2996                 :         }
    2997                 : 
    2998               0 :         *len = nlen;
    2999               0 : }
    3000                 : /* }}} */
    3001                 :                         
    3002                 : /* {{{ php_addcslashes
    3003                 :  */
    3004                 : PHPAPI char *php_addcslashes(char *str, int length, int *new_length, int should_free, char *what, int wlength TSRMLS_DC)
    3005               0 : {
    3006                 :         char flags[256];
    3007               0 :         char *new_str = safe_emalloc(4, (length?length:(length=strlen(str))), 1);
    3008                 :         char *source, *target;
    3009                 :         char *end;
    3010                 :         char c;
    3011                 :         int  newlen;
    3012                 : 
    3013               0 :         if (!wlength) {
    3014               0 :                 wlength = strlen(what);
    3015                 :         }
    3016                 : 
    3017               0 :         php_charmask(what, wlength, flags TSRMLS_CC);
    3018                 : 
    3019               0 :         for (source = str, end = source + length, target = new_str; (c = *source) || (source < end); source++) {
    3020               0 :                 if (flags[(unsigned char)c]) {
    3021               0 :                         if ((unsigned char) c < 32 || (unsigned char) c > 126) {
    3022               0 :                                 *target++ = '\\';
    3023               0 :                                 switch (c) {
    3024               0 :                                         case '\n': *target++ = 'n'; break;
    3025               0 :                                         case '\t': *target++ = 't'; break;
    3026               0 :                                         case '\r': *target++ = 'r'; break;
    3027               0 :                                         case '\a': *target++ = 'a'; break;
    3028               0 :                                         case '\v': *target++ = 'v'; break;
    3029               0 :                                         case '\b': *target++ = 'b'; break;
    3030               0 :                                         case '\f': *target++ = 'f'; break;
    3031               0 :                                         default: target += sprintf(target, "%03o", (unsigned char) c);
    3032                 :                                 }
    3033               0 :                                 continue;
    3034                 :                         } 
    3035               0 :                         *target++ = '\\';
    3036                 :                 }
    3037               0 :                 *target++ = c;
    3038                 :         }
    3039               0 :         *target = 0;
    3040               0 :         newlen = target - new_str;
    3041               0 :         if (target - new_str < length * 4) {
    3042               0 :                 new_str = erealloc(new_str, newlen + 1);
    3043                 :         }
    3044               0 :         if (new_length) {
    3045               0 :                 *new_length = newlen;
    3046                 :         }
    3047               0 :         if (should_free) {
    3048               0 :                 STR_FREE(str);
    3049                 :         }
    3050               0 :         return new_str;
    3051                 : }
    3052                 : /* }}} */
    3053                 : 
    3054                 : /* {{{ php_addslashes
    3055                 :  */
    3056                 : PHPAPI char *php_addslashes(char *str, int length, int *new_length, int should_free TSRMLS_DC)
    3057            1349 : {
    3058            1349 :         return php_addslashes_ex(str, length, new_length, should_free, 0 TSRMLS_CC);
    3059                 : }
    3060                 : /* }}} */
    3061                 : 
    3062                 : /* {{{ php_addslashes_ex
    3063                 :  */
    3064                 : PHPAPI char *php_addslashes_ex(char *str, int length, int *new_length, int should_free, int ignore_sybase TSRMLS_DC)
    3065            1349 : {
    3066                 :         /* maximum string length, worst case situation */
    3067                 :         char *new_str;
    3068                 :         char *source, *target;
    3069                 :         char *end;
    3070                 :         int local_new_length;
    3071                 :                 
    3072            1349 :         if (!new_length) {
    3073               0 :                 new_length = &local_new_length;
    3074                 :         }
    3075            1349 :         if (!str) {
    3076               0 :                 *new_length = 0;
    3077               0 :                 return str;
    3078                 :         }
    3079            1349 :         new_str = (char *) safe_emalloc(2, (length ? length : (length = strlen(str))), 1);
    3080            1349 :         source = str;
    3081            1349 :         end = source + length;
    3082            1349 :         target = new_str;
    3083                 :         
    3084            1349 :         if (!ignore_sybase && PG(magic_quotes_sybase)) {
    3085               0 :                 while (source < end) {
    3086               0 :                         switch (*source) {
    3087                 :                                 case '\0':
    3088               0 :                                         *target++ = '\\';
    3089               0 :                                         *target++ = '0';
    3090               0 :                                         break;
    3091                 :                                 case '\'':
    3092               0 :                                         *target++ = '\'';
    3093               0 :                                         *target++ = '\'';
    3094               0 :                                         break;
    3095                 :                                 default:
    3096               0 :                                         *target++ = *source;
    3097                 :                                         break;
    3098                 :                         }
    3099               0 :                         source++;
    3100                 :                 }
    3101                 :         } else {
    3102            5043 :                 while (source < end) {
    3103            2345 :                         switch (*source) {
    3104                 :                                 case '\0':
    3105               0 :                                         *target++ = '\\';
    3106               0 :                                         *target++ = '0';
    3107               0 :                                         break;
    3108                 :                                 case '\'':
    3109                 :                                 case '\"':
    3110                 :                                 case '\\':
    3111               0 :                                         *target++ = '\\';
    3112                 :                                         /* break is missing *intentionally* */
    3113                 :                                 default:
    3114            2345 :                                         *target++ = *source;
    3115                 :                                         break;  
    3116                 :                         }
    3117                 :                 
    3118            2345 :                         source++;
    3119                 :                 }
    3120                 :         }
    3121                 :         
    3122            1349 :         *target = 0;
    3123            1349 :         *new_length = target - new_str;
    3124            1349 :         if (should_free) {
    3125               0 :                 STR_FREE(str);
    3126                 :         }
    3127            1349 :         new_str = (char *) erealloc(new_str, *new_length + 1);
    3128            1349 :         return new_str;
    3129                 : }
    3130                 : /* }}} */
    3131                 : 
    3132                 : #define _HEB_BLOCK_TYPE_ENG 1
    3133                 : #define _HEB_BLOCK_TYPE_HEB 2
    3134                 : #define isheb(c)      (((((unsigned char) c) >= 224) && (((unsigned char) c) <= 250)) ? 1 : 0)
    3135                 : #define _isblank(c)   (((((unsigned char) c) == ' '  || ((unsigned char) c) == '\t')) ? 1 : 0)
    3136                 : #define _isnewline(c) (((((unsigned char) c) == '\n' || ((unsigned char) c) == '\r')) ? 1 : 0)
    3137                 : 
    3138                 : /* {{{ php_char_to_str_ex
    3139                 :  */
    3140                 : PHPAPI int php_char_to_str_ex(char *str, uint len, char from, char *to, int to_len, zval *result, int case_sensitivity, int *replace_count)
    3141               0 : {
    3142               0 :         int char_count = 0;
    3143               0 :         int replaced = 0;
    3144               0 :         char *source, *target, *tmp, *source_end=str+len, *tmp_end = NULL;
    3145                 :                 
    3146               0 :         if (case_sensitivity) {
    3147               0 :                 char *p = str, *e = p + len;
    3148               0 :                 while ((p = memchr(p, from, (e - p)))) {
    3149               0 :                         char_count++;
    3150               0 :                         p++;
    3151                 :                 }
    3152                 :         } else {
    3153               0 :                 for (source = str; source < source_end; source++) {
    3154               0 :                         if (tolower(*source) == tolower(from)) {
    3155               0 :                                 char_count++;
    3156                 :                         }
    3157                 :                 }
    3158                 :         }
    3159                 : 
    3160               0 :         if (char_count == 0 && case_sensitivity) {
    3161               0 :                 ZVAL_STRINGL(result, str, len, 1);
    3162               0 :                 return 0;
    3163                 :         }
    3164                 :         
    3165               0 :         Z_STRLEN_P(result) = len + (char_count * (to_len - 1));
    3166               0 :         Z_STRVAL_P(result) = target = safe_emalloc(char_count, to_len, len + 1);
    3167               0 :         Z_TYPE_P(result) = IS_STRING;
    3168                 : 
    3169               0 :         if (case_sensitivity) {
    3170               0 :                 char *p = str, *e = p + len, *s = str;
    3171               0 :                 while ((p = memchr(p, from, (e - p)))) {
    3172               0 :                         memcpy(target, s, (p - s));
    3173               0 :                         target += p - s;
    3174               0 :                         memcpy(target, to, to_len);
    3175               0 :                         target += to_len;
    3176               0 :                         p++;
    3177               0 :                         s = p;
    3178               0 :                         if (replace_count) {
    3179               0 :                                 *replace_count += 1;
    3180                 :                         }
    3181                 :                 }
    3182               0 :                 if (s < e) {
    3183               0 :                         memcpy(target, s, (e - s));
    3184               0 :                         target += e - s;
    3185                 :                 }
    3186                 :         } else {
    3187               0 :                 for (source = str; source < source_end; source++) {
    3188               0 :                         if (tolower(*source) == tolower(from)) {
    3189               0 :                                 replaced = 1;
    3190               0 :                                 if (replace_count) {
    3191               0 :                                         *replace_count += 1;
    3192                 :                                 }
    3193               0 :                                 for (tmp = to, tmp_end = tmp+to_len; tmp < tmp_end; tmp++) {
    3194               0 :                                         *target = *tmp;
    3195               0 :                                         target++;
    3196                 :                                 }
    3197                 :                         } else {
    3198               0 :                                 *target = *source;
    3199               0 :                                 target++;
    3200                 :                         }
    3201                 :                 }
    3202                 :         }
    3203               0 :         *target = 0;
    3204               0 :         return replaced;
    3205                 : }
    3206                 : /* }}} */
    3207                 : 
    3208                 : /* {{{ php_char_to_str
    3209                 :  */
    3210                 : PHPAPI int php_char_to_str(char *str, uint len, char from, char *to, int to_len, zval *result)
    3211               0 : {
    3212               0 :         return php_char_to_str_ex(str, len, from, to, to_len, result, 1, NULL);
    3213                 : }
    3214                 : /* }}} */
    3215                 : 
    3216                 : /* {{{ php_str_to_str_ex
    3217                 :  */
    3218                 : PHPAPI char *php_str_to_str_ex(char *haystack, int length, 
    3219                 :         char *needle, int needle_len, char *str, int str_len, int *_new_length, int case_sensitivity, int *replace_count)
    3220            1183 : {
    3221                 :         char *new_str;
    3222                 : 
    3223            1183 :         if (needle_len < length) {
    3224            1183 :                 char *end, *haystack_dup = NULL, *needle_dup = NULL;
    3225                 :                 char *e, *s, *p, *r;
    3226                 : 
    3227            1183 :                 if (needle_len == str_len) {
    3228             107 :                         new_str = estrndup(haystack, length);
    3229             107 :                         *_new_length = length;
    3230                 : 
    3231             107 :                         if (case_sensitivity) {
    3232             107 :                                 end = new_str + length;
    3233             107 :                                 for (p = new_str; (r = php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
    3234               0 :                                         memcpy(r, str, str_len);
    3235               0 :                                         if (replace_count) {
    3236               0 :                                                 (*replace_count)++;
    3237                 :                                         }
    3238                 :                                 }
    3239                 :                         } else {
    3240               0 :                                 haystack_dup = estrndup(haystack, length);
    3241               0 :                                 needle_dup = estrndup(needle, needle_len);
    3242               0 :                                 php_strtolower(haystack_dup, length);
    3243               0 :                                 php_strtolower(needle_dup, needle_len);
    3244               0 :                                 end = haystack_dup + length;
    3245               0 :                                 for (p = haystack_dup; (r = php_memnstr(p, needle_dup, needle_len, end)); p = r + needle_len) {
    3246               0 :                                         memcpy(new_str + (r - haystack_dup), str, str_len);
    3247               0 :                                         if (replace_count) {
    3248               0 :                                                 (*replace_count)++;
    3249                 :                                         }
    3250                 :                                 }
    3251               0 :                                 efree(haystack_dup);
    3252               0 :                                 efree(needle_dup);
    3253                 :                         }
    3254             107 :                         return new_str;
    3255                 :                 } else {
    3256            1076 :                         if (!case_sensitivity) {
    3257               0 :                                 haystack_dup = estrndup(haystack, length);
    3258               0 :                                 needle_dup = estrndup(needle, needle_len);
    3259               0 :                                 php_strtolower(haystack_dup, length);
    3260               0 :                                 php_strtolower(needle_dup, needle_len);
    3261                 :                         }
    3262                 : 
    3263            1076 :                         if (str_len < needle_len) {
    3264             434 :                                 new_str = emalloc(length + 1);
    3265                 :                         } else {
    3266             642 :                                 int count = 0;
    3267                 :                                 char *o, *n, *endp;
    3268                 : 
    3269             642 :                                 if (case_sensitivity) {
    3270             642 :                                         o = haystack;
    3271             642 :                                         n = needle;
    3272                 :                                 } else {
    3273               0 :                                         o = haystack_dup;
    3274               0 :                                         n = needle_dup;
    3275                 :                                 }
    3276             642 :                                 endp = o + length;
    3277                 : 
    3278            1801 :                                 while ((o = php_memnstr(o, n, needle_len, endp))) {
    3279             517 :                                         o += needle_len;
    3280             517 :                                         count++;
    3281                 :                                 }
    3282             642 :                                 if (count == 0) {
    3283                 :                                         /* Needle doesn't occur, shortcircuit the actual replacement. */
    3284             505 :                                         if (haystack_dup) {
    3285               0 :                                                 efree(haystack_dup);
    3286                 :                                         }
    3287             505 :                                         if (needle_dup) {
    3288               0 :                                                 efree(needle_dup);
    3289                 :                                         }
    3290             505 :                                         new_str = estrndup(haystack, length);
    3291             505 :                                         if (_new_length) {
    3292             505 :                                                 *_new_length = length;
    3293                 :                                         }
    3294             505 :                                         return new_str;
    3295                 :                                 } else {
    3296             137 :                                         new_str = safe_emalloc(count, str_len - needle_len, length + 1);
    3297                 :                                 }
    3298                 :                         }
    3299                 : 
    3300             571 :                         e = s = new_str;
    3301                 : 
    3302             571 :                         if (case_sensitivity) {
    3303             571 :                                 end = haystack + length;
    3304            1745 :                                 for (p = haystack; (r = php_memnstr(p, needle, needle_len, end)); p = r + needle_len) {
    3305            1174 :                                         memcpy(e, p, r - p);
    3306            1174 :                                         e += r - p;
    3307            1174 :                                         memcpy(e, str, str_len);
    3308            1174 :                                         e += str_len;
    3309            1174 :                                         if (replace_count) {
    3310               0 :                                                 (*replace_count)++;
    3311                 :                                         }
    3312                 :                                 }
    3313                 : 
    3314             571 :                                 if (p < end) {
    3315             562 :                                         memcpy(e, p, end - p);
    3316             562 :                                         e += end - p;
    3317                 :                                 }
    3318                 :                         } else {
    3319               0 :                                 end = haystack_dup + length;
    3320                 : 
    3321               0 :                                 for (p = haystack_dup; (r = php_memnstr(p, needle_dup, needle_len, end)); p = r + needle_len) {
    3322               0 :                                         memcpy(e, haystack + (p - haystack_dup), r - p);
    3323               0 :                                         e += r - p;
    3324               0 :                                         memcpy(e, str, str_len);
    3325               0 :                                         e += str_len;
    3326               0 :                                         if (replace_count) {
    3327               0 :                                                 (*replace_count)++;
    3328                 :                                         }
    3329                 :                                 }
    3330                 : 
    3331               0 :                                 if (p < end) {
    3332               0 :                                         memcpy(e, haystack + (p - haystack_dup), end - p);
    3333               0 :                                         e += end - p;
    3334                 :                                 }
    3335                 :                         }
    3336                 : 
    3337             571 :                         if (haystack_dup) {
    3338               0 :                                 efree(haystack_dup);
    3339                 :                         }
    3340             571 :                         if (needle_dup) {
    3341               0 :                                 efree(needle_dup);
    3342                 :                         }
    3343                 : 
    3344             571 :                         *e = '\0';
    3345             571 :                         *_new_length = e - s;
    3346                 : 
    3347             571 :                         new_str = erealloc(new_str, *_new_length + 1);
    3348             571 :                         return new_str;
    3349                 :                 }
    3350               0 :         } else if (needle_len > length) {
    3351               0 : nothing_todo:
    3352               0 :                 *_new_length = length;
    3353               0 :                 new_str = estrndup(haystack, length);
    3354               0 :                 return new_str;
    3355                 :         } else {
    3356               0 :                 if (case_sensitivity && memcmp(haystack, needle, length)) {
    3357                 :                         goto nothing_todo;
    3358               0 :                 } else if (!case_sensitivity) {
    3359                 :                         char *l_haystack, *l_needle;
    3360                 : 
    3361               0 :                         l_haystack = estrndup(haystack, length);
    3362               0 :                         l_needle = estrndup(needle, length);
    3363                 : 
    3364               0 :                         php_strtolower(l_haystack, length);
    3365               0 :                         php_strtolower(l_needle, length);
    3366                 : 
    3367               0 :                         if (memcmp(l_haystack, l_needle, length)) {
    3368               0 :                                 efree(l_haystack);
    3369               0 :                                 efree(l_needle);
    3370               0 :                                 goto nothing_todo;
    3371                 :                         }
    3372               0 :                         efree(l_haystack);
    3373               0 :                         efree(l_needle);
    3374                 :                 }
    3375                 : 
    3376               0 :                 *_new_length = str_len;
    3377               0 :                 new_str = estrndup(str, str_len);
    3378                 : 
    3379               0 :                 if (replace_count) {
    3380               0 :                         (*replace_count)++;
    3381                 :                 }
    3382               0 :                 return new_str;
    3383                 :         }
    3384                 : 
    3385                 : }
    3386                 : /* }}} */
    3387                 : 
    3388                 : /* {{{ php_str_to_str
    3389                 :  */
    3390                 : PHPAPI char *php_str_to_str(char *haystack, int length, 
    3391                 :         char *needle, int needle_len, char *str, int str_len, int *_new_length)
    3392               0 : {
    3393               0 :         return php_str_to_str_ex(haystack, length, needle, needle_len, str, str_len, _new_length, 1, NULL);
    3394                 : } 
    3395                 : /* }}}
    3396                 :  */
    3397                 : 
    3398                 : /* {{{ php_str_replace_in_subject
    3399                 :  */
    3400                 : static void php_str_replace_in_subject(zval *search, zval *replace, zval **subject, zval *result, int case_sensitivity, int *replace_count)
    3401            1184 : {
    3402                 :         zval            **search_entry,
    3403            1184 :                                 **replace_entry = NULL,
    3404                 :                                   temp_result;
    3405            1184 :         char            *replace_value = NULL;
    3406            1184 :         int                      replace_len = 0;
    3407                 : 
    3408                 :         /* Make sure we're dealing with strings. */     
    3409            1184 :         convert_to_string_ex(subject);
    3410            1184 :         Z_TYPE_P(result) = IS_STRING;
    3411            1184 :         if (Z_STRLEN_PP(subject) == 0) {
    3412               1 :                 ZVAL_STRINGL(result, "", 0, 1);
    3413               1 :                 return;
    3414                 :         }
    3415                 :         
    3416                 :         /* If search is an array */
    3417            1183 :         if (Z_TYPE_P(search) == IS_ARRAY) {
    3418                 :                 /* Duplicate subject string for repeated replacement */
    3419               0 :                 *result = **subject;
    3420               0 :                 zval_copy_ctor(result);
    3421               0 :                 INIT_PZVAL(result);
    3422                 :                 
    3423               0 :                 zend_hash_internal_pointer_reset(Z_ARRVAL_P(search));
    3424                 : 
    3425               0 :                 if (Z_TYPE_P(replace) == IS_ARRAY) {
    3426               0 :                         zend_hash_internal_pointer_reset(Z_ARRVAL_P(replace));
    3427                 :                 } else {
    3428                 :                         /* Set replacement value to the passed one */
    3429               0 :                         replace_value = Z_STRVAL_P(replace);
    3430               0 :                         replace_len = Z_STRLEN_P(replace);
    3431                 :                 }
    3432                 : 
    3433                 :                 /* For each entry in the search array, get the entry */
    3434               0 :                 while (zend_hash_get_current_data(Z_ARRVAL_P(search), (void **) &search_entry) == SUCCESS) {
    3435                 :                         /* Make sure we're dealing with strings. */     
    3436               0 :                         SEPARATE_ZVAL(search_entry);
    3437               0 :                         convert_to_string(*search_entry);
    3438               0 :                         if (Z_STRLEN_PP(search_entry) == 0) {
    3439               0 :                                 zend_hash_move_forward(Z_ARRVAL_P(search));
    3440               0 :                                 if (Z_TYPE_P(replace) == IS_ARRAY) {
    3441               0 :                                         zend_hash_move_forward(Z_ARRVAL_P(replace));
    3442                 :                                 }
    3443               0 :                                 continue;
    3444                 :                         }
    3445                 : 
    3446                 :                         /* If replace is an array. */
    3447               0 :                         if (Z_TYPE_P(replace) == IS_ARRAY) {
    3448                 :                                 /* Get current entry */
    3449               0 :                                 if (zend_hash_get_current_data(Z_ARRVAL_P(replace), (void **)&replace_entry) == SUCCESS) {
    3450                 :                                         /* Make sure we're dealing with strings. */     
    3451               0 :                                         convert_to_string_ex(replace_entry);
    3452                 :                                         
    3453                 :                                         /* Set replacement value to the one we got from array */
    3454               0 :                                         replace_value = Z_STRVAL_PP(replace_entry);
    3455               0 :                                         replace_len = Z_STRLEN_PP(replace_entry);
    3456                 : 
    3457               0 :                                         zend_hash_move_forward(Z_ARRVAL_P(replace));
    3458                 :                                 } else {
    3459                 :                                         /* We've run out of replacement strings, so use an empty one. */
    3460               0 :                                         replace_value = "";
    3461               0 :                                         replace_len = 0;
    3462                 :                                 }
    3463                 :                         }
    3464                 :                         
    3465               0 :                         if (Z_STRLEN_PP(search_entry) == 1) {
    3466               0 :                                 php_char_to_str_ex(Z_STRVAL_P(result),
    3467                 :                                                                 Z_STRLEN_P(result),
    3468                 :                                                                 Z_STRVAL_PP(search_entry)[0],
    3469                 :                                                                 replace_value,
    3470                 :                                                                 replace_len,
    3471                 :                                                                 &temp_result,
    3472                 :                                                                 case_sensitivity,
    3473                 :                                                                 replace_count);
    3474               0 :                         } else if (Z_STRLEN_PP(search_entry) > 1) {
    3475               0 :                                 Z_STRVAL(temp_result) = php_str_to_str_ex(Z_STRVAL_P(result), Z_STRLEN_P(result),
    3476                 :                                                                                                                    Z_STRVAL_PP(search_entry), Z_STRLEN_PP(search_entry),
    3477                 :                                                                                                                    replace_value, replace_len, &Z_STRLEN(temp_result), case_sensitivity, replace_count);
    3478                 :                         }
    3479                 : 
    3480               0 :                         efree(Z_STRVAL_P(result));
    3481               0 :                         Z_STRVAL_P(result) = Z_STRVAL(temp_result);
    3482               0 :                         Z_STRLEN_P(result) = Z_STRLEN(temp_result);
    3483                 : 
    3484               0 :                         if (Z_STRLEN_P(result) == 0) {
    3485               0 :                                 return;
    3486                 :                         }
    3487                 : 
    3488               0 :                         zend_hash_move_forward(Z_ARRVAL_P(search));
    3489                 :                 }
    3490                 :         } else {
    3491            1183 :                 if (Z_STRLEN_P(search) == 1) {
    3492               0 :                         php_char_to_str_ex(Z_STRVAL_PP(subject),
    3493                 :                                                         Z_STRLEN_PP(subject),
    3494                 :                                                         Z_STRVAL_P(search)[0],
    3495                 :                                                         Z_STRVAL_P(replace),
    3496                 :                                                         Z_STRLEN_P(replace),
    3497                 :                                                         result,
    3498                 :                                                         case_sensitivity,
    3499                 :                                                         replace_count);
    3500            1183 :                 } else if (Z_STRLEN_P(search) > 1) {
    3501            1183 :                         Z_STRVAL_P(result) = php_str_to_str_ex(Z_STRVAL_PP(subject), Z_STRLEN_PP(subject),
    3502                 :                                                                                                         Z_STRVAL_P(search), Z_STRLEN_P(search),
    3503                 :                                                                                                         Z_STRVAL_P(replace), Z_STRLEN_P(replace), &Z_STRLEN_P(result), case_sensitivity, replace_count);
    3504                 :                 } else {
    3505               0 :                         *result = **subject;
    3506               0 :                         zval_copy_ctor(result);
    3507               0 :                         INIT_PZVAL(result);
    3508                 :                 }
    3509                 :         }
    3510                 : }
    3511                 : /* }}} */
    3512                 : 
    3513                 : /* {{{ php_str_replace_common
    3514                 :  */
    3515                 : static void php_str_replace_common(INTERNAL_FUNCTION_PARAMETERS, int case_sensitivity)
    3516            1184 : {
    3517                 :         zval **subject, **search, **replace, **subject_entry, **zcount;
    3518                 :         zval *result;
    3519                 :         char *string_key;
    3520                 :         uint string_key_len;
    3521                 :         ulong num_key;
    3522            1184 :         int count = 0;
    3523            1184 :         int argc = ZEND_NUM_ARGS();
    3524                 : 
    3525            1184 :         if (argc < 3 || argc > 4 ||
    3526                 :            zend_get_parameters_ex(argc, &search, &replace, &subject, &zcount) == FAILURE) {
    3527               0 :                 WRONG_PARAM_COUNT;
    3528                 :         }
    3529                 : 
    3530            1184 :         SEPARATE_ZVAL(search);
    3531            1184 :         SEPARATE_ZVAL(replace);
    3532            1184 :         SEPARATE_ZVAL(subject);
    3533                 : 
    3534                 :         /* Make sure we're dealing with strings and do the replacement. */
    3535            1184 :         if (Z_TYPE_PP(search) != IS_ARRAY) {
    3536            1184 :                 convert_to_string_ex(search);
    3537            1184 :                 convert_to_string_ex(replace);
    3538               0 :         } else if (Z_TYPE_PP(replace) != IS_ARRAY) {
    3539               0 :                 convert_to_string_ex(replace);
    3540                 :         }
    3541                 : 
    3542                 :         /* if subject is an array */
    3543            1184 :         if (Z_TYPE_PP(subject) == IS_ARRAY) {
    3544               0 :                 array_init(return_value);
    3545               0 :                 zend_hash_internal_pointer_reset(Z_ARRVAL_PP(subject));
    3546                 : 
    3547                 :                 /* For each subject entry, convert it to string, then perform replacement
    3548                 :                    and add the result to the return_value array. */
    3549               0 :                 while (zend_hash_get_current_data(Z_ARRVAL_PP(subject), (void **)&subject_entry) == SUCCESS) {
    3550               0 :                         if (Z_TYPE_PP(subject_entry) != IS_ARRAY && Z_TYPE_PP(subject_entry) != IS_OBJECT) {
    3551               0 :                                 MAKE_STD_ZVAL(result);
    3552               0 :                                 SEPARATE_ZVAL(subject_entry);
    3553               0 :                                 php_str_replace_in_subject(*search, *replace, subject_entry, result, case_sensitivity, (argc > 3) ? &count : NULL);
    3554                 :                         } else {
    3555               0 :                                 ALLOC_ZVAL(result);
    3556               0 :                                 ZVAL_ADDREF(*subject_entry);
    3557               0 :                                 COPY_PZVAL_TO_ZVAL(*result, *subject_entry);
    3558                 :                         }
    3559                 :                         /* Add to return array */
    3560                 :                         switch (zend_hash_get_current_key_ex(Z_ARRVAL_PP(subject), &string_key,
    3561               0 :                                                                                                 &string_key_len, &num_key, 0, NULL)) {
    3562                 :                                 case HASH_KEY_IS_STRING:
    3563               0 :                                         add_assoc_zval_ex(return_value, string_key, string_key_len, result);
    3564               0 :                                         break;
    3565                 : 
    3566                 :                                 case HASH_KEY_IS_LONG:
    3567               0 :                                         add_index_zval(return_value, num_key, result);
    3568                 :                                         break;
    3569                 :                         }
    3570                 :                 
    3571               0 :                         zend_hash_move_forward(Z_ARRVAL_PP(subject));
    3572                 :                 }
    3573                 :         } else {        /* if subject is not an array */
    3574            1184 :                 php_str_replace_in_subject(*search, *replace, subject, return_value, case_sensitivity, (argc > 3) ? &count : NULL);
    3575                 :         }       
    3576            1184 :         if (argc > 3) {
    3577               0 :                 zval_dtor(*zcount);
    3578               0 :                 ZVAL_LONG(*zcount, count);
    3579                 :         }
    3580                 : }
    3581                 : /* }}} */
    3582                 : 
    3583                 : /* {{{ proto mixed str_replace(mixed search, mixed replace, mixed subject [, int &replace_count])
    3584                 :    Replaces all occurrences of search in haystack with replace */
    3585                 : PHP_FUNCTION(str_replace)
    3586            1184 : {
    3587            1184 :         php_str_replace_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    3588            1184 : }
    3589                 : /* }}} */
    3590                 : 
    3591                 : /* {{{ proto mixed str_ireplace(mixed search, mixed replace, mixed subject [, int &replace_count])
    3592                 :    Replaces all occurrences of search in haystack with replace / case-insensitive */
    3593                 : PHP_FUNCTION(str_ireplace)
    3594               0 : {
    3595               0 :         php_str_replace_common(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    3596               0 : }
    3597                 : /* }}} */
    3598                 : 
    3599                 : /* {{{ php_hebrev
    3600                 :  *
    3601                 :  * Converts Logical Hebrew text (Hebrew Windows style) to Visual text
    3602                 :  * Cheers/complaints/flames - Zeev Suraski <zeev@php.net>
    3603                 :  */
    3604                 : static void php_hebrev(INTERNAL_FUNCTION_PARAMETERS, int convert_newlines)
    3605               0 : {
    3606                 :         zval **str, **max_chars_per_line;
    3607                 :         char *heb_str, *tmp, *target, *broken_str;
    3608                 :         int block_start, block_end, block_type, block_length, i;
    3609               0 :         long max_chars=0;
    3610                 :         int begin, end, char_count, orig_begin;
    3611                 : 
    3612                 :         
    3613               0 :         switch (ZEND_NUM_ARGS()) {
    3614                 :                 case 1:
    3615               0 :                         if (zend_get_parameters_ex(1, &str) == FAILURE) {
    3616               0 :                                 RETURN_FALSE;
    3617                 :                         }
    3618               0 :                         break;
    3619                 :                 case 2:
    3620               0 :                         if (zend_get_parameters_ex(2, &str, &max_chars_per_line) == FAILURE) {
    3621               0 :                                 RETURN_FALSE;
    3622                 :                         }
    3623               0 :                         convert_to_long_ex(max_chars_per_line);
    3624               0 :                         max_chars = Z_LVAL_PP(max_chars_per_line);
    3625               0 :                         break;
    3626                 :                 default:
    3627               0 :                         WRONG_PARAM_COUNT;
    3628                 :                         break;
    3629                 :         }
    3630                 :         
    3631               0 :         convert_to_string_ex(str);
    3632                 :         
    3633               0 :         if (Z_STRLEN_PP(str) == 0) {
    3634               0 :                 RETURN_FALSE;
    3635                 :         }
    3636                 : 
    3637               0 :         tmp = Z_STRVAL_PP(str);
    3638               0 :         block_start=block_end=0;
    3639                 : 
    3640               0 :         heb_str = (char *) emalloc(Z_STRLEN_PP(str)+1);
    3641               0 :         target = heb_str+Z_STRLEN_PP(str);
    3642               0 :         *target = 0;
    3643               0 :         target--;
    3644                 : 
    3645               0 :         block_length=0;
    3646                 : 
    3647               0 :         if (isheb(*tmp)) {
    3648               0 :                 block_type = _HEB_BLOCK_TYPE_HEB;
    3649                 :         } else {
    3650               0 :                 block_type = _HEB_BLOCK_TYPE_ENG;
    3651                 :         }
    3652                 :         
    3653                 :         do {
    3654               0 :                 if (block_type == _HEB_BLOCK_TYPE_HEB) {
    3655               0 :                         while ((isheb((int)*(tmp+1)) || _isblank((int)*(tmp+1)) || ispunct((int)*(tmp+1)) || (int)*(tmp+1)=='\n' ) && block_end<Z_STRLEN_PP(str)-1) {
    3656               0 :                                 tmp++;
    3657               0 :                                 block_end++;
    3658               0 :                                 block_length++;
    3659                 :                         }
    3660               0 :                         for (i = block_start; i<= block_end; i++) {
    3661               0 :                                 *target = Z_STRVAL_PP(str)[i];
    3662               0 :                                 switch (*target) {
    3663                 :                                         case '(':
    3664               0 :                                                 *target = ')';
    3665               0 :                                                 break;
    3666                 :                                         case ')':
    3667               0 :                                                 *target = '(';
    3668               0 :                                                 break;
    3669                 :                                         case '[':
    3670               0 :                                                 *target = ']';
    3671               0 :                                                 break;
    3672                 :                                         case ']':
    3673               0 :                                                 *target = '[';
    3674               0 :                                                 break;
    3675                 :                                         case '{':
    3676               0 :                                                 *target = '}';
    3677               0 :                                                 break;
    3678                 :                                         case '}':
    3679               0 :                                                 *target = '{';
    3680               0 :                                                 break;
    3681                 :                                         case '<':
    3682               0 :                                                 *target = '>';
    3683               0 :                                                 break;
    3684                 :                                         case '>':
    3685               0 :                                                 *target = '<';
    3686               0 :                                                 break;
    3687                 :                                         case '\\':
    3688               0 :                                                 *target = '/';
    3689               0 :                                                 break;
    3690                 :                                         case '/':
    3691               0 :                                                 *target = '\\';
    3692                 :                                                 break;
    3693                 :                                         default:
    3694                 :                                                 break;
    3695                 :                                 }
    3696               0 :                                 target--;
    3697                 :                         }
    3698               0 :                         block_type = _HEB_BLOCK_TYPE_ENG;
    3699                 :                 } else {
    3700               0 :                         while (!isheb(*(tmp+1)) && (int)*(tmp+1)!='\n' && block_end < Z_STRLEN_PP(str)-1) {
    3701               0 :                                 tmp++;
    3702               0 :                                 block_end++;
    3703               0 :                                 block_length++;
    3704                 :                         }
    3705               0 :                         while ((_isblank((int)*tmp) || ispunct((int)*tmp)) && *tmp!='/' && *tmp!='-' && block_end > block_start) {
    3706               0 :                                 tmp--;
    3707               0 :                                 block_end--;
    3708                 :                         }
    3709               0 :                         for (i = block_end; i >= block_start; i--) {
    3710               0 :                                 *target = Z_STRVAL_PP(str)[i];
    3711               0 :                                 target--;
    3712                 :                         }
    3713               0 :                         block_type = _HEB_BLOCK_TYPE_HEB;
    3714                 :                 }
    3715               0 :                 block_start=block_end+1;
    3716               0 :         } while (block_end < Z_STRLEN_PP(str)-1);
    3717                 : 
    3718                 : 
    3719               0 :         broken_str = (char *) emalloc(Z_STRLEN_PP(str)+1);
    3720               0 :         begin=end=Z_STRLEN_PP(str)-1;
    3721               0 :         target = broken_str;
    3722                 :                 
    3723                 :         while (1) {
    3724               0 :                 char_count=0;
    3725               0 :                 while ((!max_chars || char_count < max_chars) && begin > 0) {
    3726               0 :                         char_count++;
    3727               0 :                         begin--;
    3728               0 :                         if (begin <= 0 || _isnewline(heb_str[begin])) {
    3729               0 :                                 while (begin > 0 && _isnewline(heb_str[begin-1])) {
    3730               0 :                                         begin--;
    3731               0 :                                         char_count++;
    3732                 :                                 }
    3733               0 :                                 break;
    3734                 :                         }
    3735                 :                 }
    3736               0 :                 if (char_count == max_chars) { /* try to avoid breaking words */
    3737               0 :                         int new_char_count=char_count, new_begin=begin;
    3738                 :                         
    3739               0 :                         while (new_char_count > 0) {
    3740               0 :                                 if (_isblank(heb_str[new_begin]) || _isnewline(heb_str[new_begin])) {
    3741                 :                                         break;
    3742                 :                                 }
    3743               0 :                                 new_begin++;
    3744               0 :                                 new_char_count--;
    3745                 :                         }
    3746               0 :                         if (new_char_count > 0) {
    3747               0 :                                 char_count=new_char_count;
    3748               0 :                                 begin=new_begin;
    3749                 :                         }
    3750                 :                 }
    3751               0 :                 orig_begin=begin;
    3752                 :                 
    3753               0 :                 if (_isblank(heb_str[begin])) {
    3754               0 :                         heb_str[begin]='\n';
    3755                 :                 }
    3756               0 :                 while (begin <= end && _isnewline(heb_str[begin])) { /* skip leading newlines */
    3757               0 :                         begin++;
    3758                 :                 }
    3759               0 :                 for (i = begin; i <= end; i++) { /* copy content */
    3760               0 :                         *target = heb_str[i];
    3761               0 :                         target++;
    3762                 :                 }
    3763               0 :                 for (i = orig_begin; i <= end && _isnewline(heb_str[i]); i++) {
    3764               0 :                         *target = heb_str[i];
    3765               0 :                         target++;
    3766                 :                 }
    3767               0 :                 begin=orig_begin;
    3768                 : 
    3769               0 :                 if (begin <= 0) {
    3770               0 :                         *target = 0;
    3771                 :                         break;
    3772                 :                 }
    3773               0 :                 begin--;
    3774               0 :                 end=begin;
    3775               0 :         }
    3776               0 :         efree(heb_str);
    3777                 : 
    3778               0 :         if (convert_newlines) {
    3779               0 :                 php_char_to_str(broken_str, Z_STRLEN_PP(str),'\n', "<br />\n", 7, return_value);
    3780               0 :                 efree(broken_str);
    3781                 :         } else {
    3782               0 :                 Z_STRVAL_P(return_value) = broken_str;
    3783               0 :                 Z_STRLEN_P(return_value) = Z_STRLEN_PP(str);
    3784               0 :                 Z_TYPE_P(return_value) = IS_STRING;
    3785                 :         }
    3786                 : }
    3787                 : /* }}} */
    3788                 : 
    3789                 : /* {{{ proto string hebrev(string str [, int max_chars_per_line])
    3790                 :    Converts logical Hebrew text to visual text */
    3791                 : PHP_FUNCTION(hebrev)
    3792               0 : {
    3793               0 :         php_hebrev(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    3794               0 : }
    3795                 : /* }}} */
    3796                 : 
    3797                 : /* {{{ proto string hebrevc(string str [, int max_chars_per_line])
    3798                 :    Converts logical Hebrew text to visual text with newline conversion */
    3799                 : PHP_FUNCTION(hebrevc)
    3800               0 : {
    3801               0 :         php_hebrev(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    3802               0 : }
    3803                 : /* }}} */
    3804                 : 
    3805                 : 
    3806                 : /* {{{ proto string nl2br(string str)
    3807                 :    Converts newlines to HTML line breaks */
    3808                 : PHP_FUNCTION(nl2br)
    3809               0 : {
    3810                 :         /* in brief this inserts <br /> before matched regexp \n\r?|\r\n? */
    3811                 :         zval    **zstr;
    3812                 :         char    *tmp, *str;
    3813                 :         int     new_length;
    3814                 :         char    *end, *target;
    3815               0 :         int     repl_cnt = 0;
    3816                 : 
    3817               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &zstr) == FAILURE) {
    3818               0 :                 WRONG_PARAM_COUNT;
    3819                 :         }
    3820                 :         
    3821               0 :         convert_to_string_ex(zstr);
    3822                 : 
    3823               0 :         str = Z_STRVAL_PP(zstr);
    3824               0 :         end = str + Z_STRLEN_PP(zstr);
    3825                 :         
    3826                 :         /* it is really faster to scan twice and allocate mem once insted scanning once
    3827                 :            and constantly reallocing */
    3828               0 :         while (str < end) {
    3829               0 :                 if (*str == '\r') {
    3830               0 :                         if (*(str+1) == '\n') {
    3831               0 :                                 str++;
    3832                 :                         }
    3833               0 :                         repl_cnt++;
    3834               0 :                 } else if (*str == '\n') {
    3835               0 :                         if (*(str+1) == '\r') {
    3836               0 :                                 str++;
    3837                 :                         }
    3838               0 :                         repl_cnt++;
    3839                 :                 }
    3840                 :                 
    3841               0 :                 str++;
    3842                 :         }
    3843                 :         
    3844               0 :         if (repl_cnt == 0) {
    3845               0 :                 RETURN_STRINGL(Z_STRVAL_PP(zstr), Z_STRLEN_PP(zstr), 1);
    3846                 :         }
    3847                 : 
    3848               0 :         new_length = Z_STRLEN_PP(zstr) + repl_cnt * (sizeof("<br />") - 1);
    3849               0 :         tmp = target = emalloc(new_length + 1);
    3850                 : 
    3851               0 :         str = Z_STRVAL_PP(zstr);
    3852                 : 
    3853               0 :         while (str < end) {
    3854               0 :                 switch (*str) {
    3855                 :                         case '\r':
    3856                 :                         case '\n':
    3857               0 :                                 *target++ = '<';
    3858               0 :                                 *target++ = 'b';
    3859               0 :                                 *target++ = 'r';
    3860               0 :                                 *target++ = ' ';
    3861               0 :                                 *target++ = '/';
    3862               0 :                                 *target++ = '>';
    3863                 :                                 
    3864               0 :                                 if ((*str == '\r' && *(str+1) == '\n') || (*str == '\n' && *(str+1) == '\r')) {
    3865               0 :                                         *target++ = *str++;
    3866                 :                                 }
    3867                 :                                 /* lack of a break; is intentional */
    3868                 :                         default:
    3869               0 :                                 *target++ = *str;
    3870                 :                 }
    3871                 :         
    3872               0 :                 str++;
    3873                 :         }
    3874                 :         
    3875               0 :         *target = '\0';
    3876                 : 
    3877               0 :         RETURN_STRINGL(tmp, new_length, 0);
    3878                 : }
    3879                 : /* }}} */
    3880                 : 
    3881                 : 
    3882                 : /* {{{ proto string strip_tags(string str [, string allowable_tags])
    3883                 :    Strips HTML and PHP tags from a string */
    3884                 : PHP_FUNCTION(strip_tags)
    3885               0 : {
    3886                 :         char *buf;
    3887               0 :         zval **str, **allow=NULL;
    3888               0 :         char *allowed_tags=NULL;
    3889               0 :         int allowed_tags_len=0;
    3890                 :         size_t retval_len;
    3891                 : 
    3892               0 :         switch (ZEND_NUM_ARGS()) {
    3893                 :                 case 1:
    3894               0 :                         if (zend_get_parameters_ex(1, &str) == FAILURE) {
    3895               0 :                                 RETURN_FALSE;
    3896                 :                         }
    3897               0 :                         break;
    3898                 :                 case 2:
    3899               0 :                         if (zend_get_parameters_ex(2, &str, &allow) == FAILURE) {
    3900               0 :                                 RETURN_FALSE;
    3901                 :                         }
    3902               0 :                         convert_to_string_ex(allow);
    3903               0 :                         allowed_tags = Z_STRVAL_PP(allow);
    3904               0 :                         allowed_tags_len = Z_STRLEN_PP(allow);
    3905               0 :                         break;
    3906                 :                 default:
    3907               0 :                         WRONG_PARAM_COUNT;
    3908                 :                         break;
    3909                 :         }
    3910               0 :         convert_to_string_ex(str);
    3911               0 :         buf = estrndup(Z_STRVAL_PP(str), Z_STRLEN_PP(str));
    3912               0 :         retval_len = php_strip_tags_ex(buf, Z_STRLEN_PP(str), NULL, allowed_tags, allowed_tags_len, 0);
    3913               0 :         RETURN_STRINGL(buf, retval_len, 0);
    3914                 : }
    3915                 : /* }}} */
    3916                 : 
    3917                 : /* {{{ proto string setlocale(mixed category, string locale [, string ...])
    3918                 :    Set locale information */
    3919                 : PHP_FUNCTION(setlocale)
    3920               0 : {
    3921               0 :         zval ***args = (zval ***) safe_emalloc(sizeof(zval **), ZEND_NUM_ARGS(), 0);
    3922                 :         zval **pcategory, **plocale;
    3923               0 :         int i, cat, n_args=ZEND_NUM_ARGS();
    3924                 :         char *loc, *retval;
    3925                 : 
    3926               0 :         if (zend_get_parameters_array_ex(n_args, args) == FAILURE || n_args < 2) {
    3927               0 :                 efree(args);
    3928               0 :                 WRONG_PARAM_COUNT;
    3929                 :         }
    3930                 : #ifdef HAVE_SETLOCALE
    3931               0 :         pcategory = args[0];
    3932               0 :         if (Z_TYPE_PP(pcategory) == IS_LONG) {
    3933               0 :                 convert_to_long_ex(pcategory);  
    3934               0 :                 cat = Z_LVAL_PP(pcategory);
    3935                 :         } else { /* FIXME: The following behaviour should be removed. */
    3936                 :                 char *category;
    3937               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passing locale category name as string is deprecated. Use the LC_* -constants instead.");
    3938               0 :                 convert_to_string_ex(pcategory);
    3939               0 :                 category = Z_STRVAL_P(*pcategory);
    3940                 : 
    3941               0 :                 if (!strcasecmp ("LC_ALL", category))
    3942               0 :                         cat = LC_ALL;
    3943               0 :                 else if (!strcasecmp ("LC_COLLATE", category))
    3944               0 :                         cat = LC_COLLATE;
    3945               0 :                 else if (!strcasecmp ("LC_CTYPE", category))
    3946               0 :                         cat = LC_CTYPE;
    3947                 : #ifdef LC_MESSAGES
    3948               0 :                 else if (!strcasecmp ("LC_MESSAGES", category))
    3949               0 :                         cat = LC_MESSAGES;
    3950                 : #endif
    3951               0 :                 else if (!strcasecmp ("LC_MONETARY", category))
    3952               0 :                         cat = LC_MONETARY;
    3953               0 :                 else if (!strcasecmp ("LC_NUMERIC", category))
    3954               0 :                         cat = LC_NUMERIC;
    3955               0 :                 else if (!strcasecmp ("LC_TIME", category))
    3956               0 :                         cat = LC_TIME;
    3957                 :                 else {
    3958               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid locale category name %s, must be one of LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, or LC_TIME.", category);
    3959               0 :                         efree(args);
    3960               0 :                         RETURN_FALSE;
    3961                 :                 }
    3962                 :         }
    3963                 : 
    3964               0 :         if (Z_TYPE_PP(args[1]) == IS_ARRAY) {
    3965               0 :                 zend_hash_internal_pointer_reset(Z_ARRVAL_PP(args[1]));
    3966               0 :                 i=0; /* not needed in this case: only kill a compiler warning */
    3967                 :         } else {
    3968               0 :                 i=1;
    3969                 :         }
    3970                 :         while (1) {
    3971               0 :                 if (Z_TYPE_PP(args[1]) == IS_ARRAY) {
    3972               0 :                         if (!zend_hash_num_elements(Z_ARRVAL_PP(args[1]))) {
    3973               0 :                                 break;
    3974                 :                         }
    3975               0 :                         zend_hash_get_current_data(Z_ARRVAL_PP(args[1]),(void **)&plocale);
    3976                 :                 } else {
    3977               0 :                         plocale = args[i];
    3978                 :                 }
    3979                 : 
    3980               0 :                 convert_to_string_ex(plocale);
    3981                 :                 
    3982               0 :                 if (!strcmp ("0", Z_STRVAL_PP(plocale))) {
    3983               0 :                         loc = NULL;
    3984                 :                 } else {
    3985               0 :                         loc = Z_STRVAL_PP(plocale);
    3986                 :                 }
    3987                 :                 
    3988               0 :                 retval = setlocale (cat, loc);
    3989                 :                 zend_update_current_locale();
    3990               0 :                 if (retval) {
    3991                 :                         /* Remember if locale was changed */
    3992               0 :                         if (loc) {
    3993               0 :                                 STR_FREE(BG(locale_string));
    3994               0 :                                 BG(locale_string) = estrdup(retval);
    3995                 :                         }
    3996                 :                         
    3997               0 :                         efree(args);
    3998               0 :                         RETVAL_STRING(retval, 1);
    3999                 :                         
    4000               0 :                         return;
    4001                 :                 }
    4002                 :                 
    4003               0 :                 if (Z_TYPE_PP(args[1]) == IS_ARRAY) {
    4004               0 :                         if (zend_hash_move_forward(Z_ARRVAL_PP(args[1])) == FAILURE) break;
    4005                 :                 } else {
    4006               0 :                         if (++i >= n_args) break;
    4007                 :                 }
    4008               0 :         }
    4009                 : 
    4010                 : #endif
    4011               0 :         efree(args);
    4012                 : 
    4013               0 :         RETURN_FALSE;
    4014                 : }
    4015                 : /* }}} */
    4016                 : 
    4017                 : /* {{{ proto void parse_str(string encoded_string [, array result])
    4018                 :    Parses GET/POST/COOKIE data and sets global variables */
    4019                 : PHP_FUNCTION(parse_str)
    4020               3 : {
    4021                 :         zval **arg;
    4022                 :         zval **arrayArg;
    4023                 :         zval *sarg;
    4024               3 :         char *res = NULL;
    4025                 :         int argCount;
    4026                 : 
    4027               3 :         argCount = ZEND_NUM_ARGS();
    4028               3 :         if (argCount < 1 || argCount > 2 || zend_get_parameters_ex(argCount, &arg, &arrayArg) == FAILURE) {
    4029               0 :                 WRONG_PARAM_COUNT;
    4030                 :         }
    4031                 : 
    4032               3 :         convert_to_string_ex(arg);
    4033               3 :         sarg = *arg;
    4034               3 :         if (Z_STRVAL_P(sarg) && *Z_STRVAL_P(sarg)) {
    4035               3 :                 res = estrndup(Z_STRVAL_P(sarg), Z_STRLEN_P(sarg));
    4036                 :         }
    4037                 : 
    4038               3 :         if (argCount == 1) {
    4039                 :                 zval tmp;
    4040               0 :                 Z_ARRVAL(tmp) = EG(active_symbol_table);
    4041                 : 
    4042               0 :                 sapi_module.treat_data(PARSE_STRING, res, &tmp TSRMLS_CC);
    4043                 :         } else  {
    4044                 :                 /* Clear out the array that was passed in. */
    4045               3 :                 zval_dtor(*arrayArg);
    4046               3 :                 array_init(*arrayArg);
    4047                 :                 
    4048               3 :                 sapi_module.treat_data(PARSE_STRING, res, *arrayArg TSRMLS_CC);
    4049                 :         }
    4050                 : }
    4051                 : /* }}} */
    4052                 : 
    4053                 : #define PHP_TAG_BUF_SIZE 1023
    4054                 : 
    4055                 : /* {{{ php_tag_find
    4056                 :  *
    4057                 :  * Check if tag is in a set of tags 
    4058                 :  *
    4059                 :  * states:
    4060                 :  * 
    4061                 :  * 0 start tag
    4062                 :  * 1 first non-whitespace char seen
    4063                 :  */
    4064               0 : int php_tag_find(char *tag, int len, char *set) {
    4065                 :         char c, *n, *t;
    4066               0 :         int state=0, done=0;
    4067                 :         char *norm;
    4068                 : 
    4069               0 :         if (len <= 0) {
    4070               0 :                 return 0;
    4071                 :         }
    4072                 :         
    4073               0 :         norm = emalloc(len+1);
    4074                 : 
    4075               0 :         n = norm;
    4076               0 :         t = tag;
    4077               0 :         c = tolower(*t);
    4078                 :         /* 
    4079                 :            normalize the tag removing leading and trailing whitespace
    4080                 :            and turn any <a whatever...> into just <a> and any </tag>
    4081                 :            into <tag>
    4082                 :         */
    4083               0 :         while (!done) {
    4084               0 :                 switch (c) {
    4085                 :                         case '<':
    4086               0 :                                 *(n++) = c;
    4087               0 :                                 break;
    4088                 :                         case '>':
    4089               0 :                                 done =1;
    4090               0 :                                 break;
    4091                 :                         default:
    4092               0 :                                 if (!isspace((int)c)) {
    4093               0 :                                         if (state == 0) {
    4094               0 :                                                 state=1;
    4095               0 :                                                 if (c != '/')
    4096               0 :                                                         *(n++) = c;
    4097                 :                                         } else {
    4098               0 :                                                 *(n++) = c;
    4099                 :                                         }
    4100                 :                                 } else {
    4101               0 :                                         if (state == 1)
    4102               0 :                                                 done=1;
    4103                 :                                 }
    4104                 :                                 break;
    4105                 :                 }
    4106               0 :                 c = tolower(*(++t));
    4107                 :         }  
    4108               0 :         *(n++) = '>';
    4109               0 :         *n = '\0'; 
    4110               0 :         if (strstr(set, norm)) {
    4111               0 :                 done=1;
    4112                 :         } else {
    4113               0 :                 done=0;
    4114                 :         }
    4115               0 :         efree(norm);
    4116               0 :         return done;
    4117                 : }
    4118                 : /* }}} */
    4119                 : 
    4120                 : PHPAPI size_t php_strip_tags(char *rbuf, int len, int *stateptr, char *allow, int allow_len)
    4121               0 : {
    4122               0 :         return php_strip_tags_ex(rbuf, len, stateptr, allow, allow_len, 0);
    4123                 : }
    4124                 : 
    4125                 : /* {{{ php_strip_tags
    4126                 :  
    4127                 :         A simple little state-machine to strip out html and php tags 
    4128                 :         
    4129                 :         State 0 is the output state, State 1 means we are inside a
    4130                 :         normal html tag and state 2 means we are inside a php tag.
    4131                 : 
    4132                 :         The state variable is passed in to allow a function like fgetss
    4133                 :         to maintain state across calls to the function.
    4134                 : 
    4135                 :         lc holds the last significant character read and br is a bracket
    4136                 :         counter.
    4137                 : 
    4138                 :         When an allow string is passed in we keep track of the string
    4139                 :         in state 1 and when the tag is closed check it against the
    4140                 :         allow string to see if we should allow it.
    4141                 : 
    4142                 :         swm: Added ability to strip <?xml tags without assuming it PHP
    4143                 :         code.
    4144                 : */
    4145                 : PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow, int allow_len, zend_bool allow_tag_spaces)
    4146               0 : {
    4147                 :         char *tbuf, *buf, *p, *tp, *rp, c, lc;
    4148               0 :         int br, i=0, depth=0, in_q = 0;
    4149               0 :         int state = 0;
    4150                 : 
    4151               0 :         if (stateptr)
    4152               0 :                 state = *stateptr;
    4153                 : 
    4154               0 :         buf = estrndup(rbuf, len);
    4155               0 :         c = *buf;
    4156               0 :         lc = '\0';
    4157               0 :         p = buf;
    4158               0 :         rp = rbuf;
    4159               0 :         br = 0;
    4160               0 :         if (allow) {
    4161               0 :                 php_strtolower(allow, allow_len);
    4162               0 :                 tbuf = emalloc(PHP_TAG_BUF_SIZE+1);
    4163               0 :                 tp = tbuf;
    4164                 :         } else {
    4165               0 :                 tbuf = tp = NULL;
    4166                 :         }
    4167                 : 
    4168               0 :         while (i < len) {
    4169               0 :                 switch (c) {
    4170                 :                         case '\0':
    4171               0 :                                 break;
    4172                 :                         case '<':
    4173               0 :                                 if (isspace(*(p + 1)) && !allow_tag_spaces) {
    4174               0 :                                         goto reg_char;
    4175                 :                                 }
    4176               0 :                                 if (state == 0) {
    4177               0 :                                         lc = '<';
    4178               0 :                                         state = 1;
    4179               0 :                                         if (allow) {
    4180               0 :                                                 tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
    4181               0 :                                                 *(tp++) = '<';
    4182                 :                                         }
    4183               0 :                                 } else if (state == 1) {
    4184               0 :                                         depth++;
    4185                 :                                 }
    4186               0 :                                 break;
    4187                 : 
    4188                 :                         case '(':
    4189               0 :                                 if (state == 2) {
    4190               0 :                                         if (lc != '"' && lc != '\'') {
    4191               0 :                                                 lc = '(';
    4192               0 :                                                 br++;
    4193                 :                                         }
    4194               0 :                                 } else if (allow && state == 1) {
    4195               0 :                                         tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
    4196               0 :                                         *(tp++) = c;
    4197               0 :                                 } else if (state == 0) {
    4198               0 :                                         *(rp++) = c;
    4199                 :                                 }
    4200               0 :                                 break;  
    4201                 : 
    4202                 :                         case ')':
    4203               0 :                                 if (state == 2) {
    4204               0 :                                         if (lc != '"' && lc != '\'') {
    4205               0 :                                                 lc = ')';
    4206               0 :                                                 br--;
    4207                 :                                         }
    4208               0 :                                 } else if (allow && state == 1) {
    4209               0 :                                         tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
    4210               0 :                                         *(tp++) = c;
    4211               0 :                                 } else if (state == 0) {
    4212               0 :                                         *(rp++) = c;
    4213                 :                                 }
    4214               0 :                                 break;  
    4215                 : 
    4216                 :                         case '>':
    4217               0 :                                 if (depth) {
    4218               0 :                                         depth--;
    4219               0 :                                         break;
    4220                 :                                 }
    4221                 : 
    4222               0 :                                 if (in_q) {
    4223               0 :                                         break;
    4224                 :                                 }
    4225                 : 
    4226               0 :                                 switch (state) {
    4227                 :                                         case 1: /* HTML/XML */
    4228               0 :                                                 lc = '>';
    4229               0 :                                                 in_q = state = 0;
    4230               0 :                                                 if (allow) {
    4231               0 :                                                         tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
    4232               0 :                                                         *(tp++) = '>';
    4233               0 :                                                         *tp='\0';
    4234               0 :                                                         if (php_tag_find(tbuf, tp-tbuf, allow)) {
    4235               0 :                                                                 memcpy(rp, tbuf, tp-tbuf);
    4236               0 :                                                                 rp += tp-tbuf;
    4237                 :                                                         }
    4238               0 :                                                         tp = tbuf;
    4239                 :                                                 }
    4240               0 :                                                 break;
    4241                 :                                                 
    4242                 :                                         case 2: /* PHP */
    4243               0 :                                                 if (!br && lc != '\"' && *(p-1) == '?') {
    4244               0 :                                                         in_q = state = 0;
    4245               0 :                                                         tp = tbuf;
    4246                 :                                                 }
    4247               0 :                                                 break;
    4248                 :                                                 
    4249                 :                                         case 3:
    4250               0 :                                                 in_q = state = 0;
    4251               0 :                                                 tp = tbuf;
    4252               0 :                                                 break;
    4253                 : 
    4254                 :                                         case 4: /* JavaScript/CSS/etc... */
    4255               0 :                                                 if (p >= buf + 2 && *(p-1) == '-' && *(p-2) == '-') {
    4256               0 :                                                         in_q = state = 0;
    4257               0 :                                                         tp = tbuf;
    4258                 :                                                 }
    4259               0 :                                                 break;
    4260                 : 
    4261                 :                                         default:
    4262               0 :                                                 *(rp++) = c;
    4263                 :                                                 break;
    4264                 :                                 }
    4265               0 :                                 break;
    4266                 : 
    4267                 :                         case '"':
    4268                 :                         case '\'':
    4269               0 :                                 if (state == 2 && *(p-1) != '\\') {
    4270               0 :                                         if (lc == c) {
    4271               0 :                                                 lc = '\0';
    4272               0 :                                         } else if (lc != '\\') {
    4273               0 :                                                 lc = c;
    4274                 :                                         }
    4275               0 :                                 } else if (state == 0) {
    4276               0 :                                         *(rp++) = c;
    4277               0 :                                 } else if (allow && state == 1) {
    4278               0 :                                         tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
    4279               0 :                                         *(tp++) = c;
    4280                 :                                 }
    4281               0 :                                 if (state && p != buf && *(p-1) != '\\' && (!in_q || *p == in_q)) {
    4282               0 :                                         if (in_q) {
    4283               0 :                                                 in_q = 0;
    4284                 :                                         } else {
    4285               0 :                                                 in_q = *p;
    4286                 :                                         }
    4287                 :                                 }
    4288               0 :                                 break;
    4289                 :                         
    4290                 :                         case '!': 
    4291                 :                                 /* JavaScript & Other HTML scripting languages */
    4292               0 :                                 if (state == 1 && *(p-1) == '<') { 
    4293               0 :                                         state = 3;
    4294               0 :                                         lc = c;
    4295                 :                                 } else {
    4296               0 :                                         if (state == 0) {
    4297               0 :                                                 *(rp++) = c;
    4298               0 :                                         } else if (allow && state == 1) {
    4299               0 :                                                 tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
    4300               0 :                                                 *(tp++) = c;
    4301                 :                                         }
    4302                 :                                 }
    4303               0 :                                 break;
    4304                 : 
    4305                 :                         case '-':
    4306               0 :                                 if (state == 3 && p >= buf + 2 && *(p-1) == '-' && *(p-2) == '!') {
    4307               0 :                                         state = 4;
    4308                 :                                 } else {
    4309                 :                                         goto reg_char;
    4310                 :                                 }
    4311               0 :                                 break;
    4312                 : 
    4313                 :                         case '?':
    4314                 : 
    4315               0 :                                 if (state == 1 && *(p-1) == '<') { 
    4316               0 :                                         br=0;
    4317               0 :                                         state=2;
    4318               0 :                                         break;
    4319                 :                                 }
    4320                 : 
    4321                 :                         case 'E':
    4322                 :                         case 'e':
    4323                 :                                 /* !DOCTYPE exception */
    4324               0 :                                 if (state==3 && p > buf+6
    4325                 :                                                      && tolower(*(p-1)) == 'p'
    4326                 :                                                  && tolower(*(p-2)) == 'y'
    4327                 :                                                      && tolower(*(p-3)) == 't'
    4328                 :                                                      && tolower(*(p-4)) == 'c'
    4329                 :                                                      && tolower(*(p-5)) == 'o'
    4330                 :                                                      && tolower(*(p-6)) == 'd') {
    4331               0 :                                         state = 1;
    4332               0 :                                         break;
    4333                 :                                 }
    4334                 :                                 /* fall-through */
    4335                 : 
    4336                 :                         case 'l':
    4337                 : 
    4338                 :                                 /* swm: If we encounter '<?xml' then we shouldn't be in
    4339                 :                                  * state == 2 (PHP). Switch back to HTML.
    4340                 :                                  */
    4341                 : 
    4342               0 :                                 if (state == 2 && p > buf+2 && *(p-1) == 'm' && *(p-2) == 'x') {
    4343               0 :                                         state = 1;
    4344               0 :                                         break;
    4345                 :                                 }
    4346                 : 
    4347                 :                                 /* fall-through */
    4348                 :                         default:
    4349               0 : reg_char:
    4350               0 :                                 if (state == 0) {
    4351               0 :                                         *(rp++) = c;
    4352               0 :                                 } else if (allow && state == 1) {
    4353               0 :                                         tp = ((tp-tbuf) >= PHP_TAG_BUF_SIZE ? tbuf: tp);
    4354               0 :                                         *(tp++) = c;
    4355                 :                                 } 
    4356                 :                                 break;
    4357                 :                 }
    4358               0 :                 c = *(++p);
    4359               0 :                 i++;
    4360                 :         }       
    4361               0 :         if (rp < rbuf + len) {
    4362               0 :                 *rp = '\0';
    4363                 :         }
    4364               0 :         efree(buf);
    4365               0 :         if (allow)
    4366               0 :                 efree(tbuf);
    4367               0 :         if (stateptr)
    4368               0 :                 *stateptr = state;
    4369                 : 
    4370               0 :         return (size_t)(rp - rbuf);
    4371                 : }
    4372                 : /* }}} */
    4373                 : 
    4374                 : /* {{{ proto string str_repeat(string input, int mult)
    4375                 :    Returns the input string repeat mult times */
    4376                 : PHP_FUNCTION(str_repeat)
    4377              16 : {
    4378                 :         zval            **input_str;            /* Input string */
    4379                 :         zval            **mult;                 /* Multiplier */
    4380                 :         char            *result;                /* Resulting string */
    4381                 :         size_t          result_len;             /* Length of the resulting string */
    4382                 :         
    4383              16 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &input_str, &mult) == FAILURE) {
    4384               0 :                 WRONG_PARAM_COUNT;
    4385                 :         }
    4386                 :         
    4387                 :         /* Make sure we're dealing with proper types */
    4388              16 :         convert_to_string_ex(input_str);
    4389              16 :         convert_to_long_ex(mult);
    4390                 :         
    4391              16 :         if (Z_LVAL_PP(mult) < 0) {
    4392               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Second argument has to be greater than or equal to 0.");
    4393               0 :                 return;
    4394                 :         }
    4395                 : 
    4396                 :         /* Don't waste our time if it's empty */
    4397              16 :         if (Z_STRLEN_PP(input_str) == 0)
    4398               0 :                 RETURN_STRINGL("", 0, 1);
    4399                 :         
    4400                 :         /* ... or if the multiplier is zero */
    4401              16 :         if (Z_LVAL_PP(mult) == 0)
    4402               2 :                 RETURN_STRINGL("", 0, 1);
    4403                 :         
    4404                 :         /* Initialize the result string */      
    4405              14 :         result_len = Z_STRLEN_PP(input_str) * Z_LVAL_PP(mult);
    4406              14 :         result = (char *)safe_emalloc(Z_STRLEN_PP(input_str), Z_LVAL_PP(mult), 1);
    4407                 :         
    4408                 :         /* Heavy optimization for situations where input string is 1 byte long */
    4409              14 :         if (Z_STRLEN_PP(input_str) == 1) {
    4410               6 :                 memset(result, *(Z_STRVAL_PP(input_str)), Z_LVAL_PP(mult)); 
    4411                 :         } else {
    4412                 :                 char *s, *e, *ee;
    4413               8 :                 int l=0;
    4414               8 :                 memcpy(result, Z_STRVAL_PP(input_str), Z_STRLEN_PP(input_str));
    4415               8 :                 s = result;
    4416               8 :                 e = result + Z_STRLEN_PP(input_str);
    4417               8 :                 ee = result + result_len;
    4418                 :                 
    4419             102 :                 while (e<ee) {
    4420              86 :                         l = (e-s) < (ee-e) ? (e-s) : (ee-e);
    4421              86 :                         memmove(e, s, l);
    4422              86 :                         e += l;
    4423                 :                 }
    4424                 :         }
    4425                 : 
    4426              14 :         result[result_len] = '\0';
    4427                 :         
    4428              14 :         RETURN_STRINGL(result, result_len, 0);
    4429                 : }
    4430                 : /* }}} */
    4431                 : 
    4432                 : /* {{{ proto mixed count_chars(string input [, int mode])
    4433                 :    Returns info about what characters are used in input */
    4434                 : PHP_FUNCTION(count_chars)
    4435               0 : {
    4436                 :         zval **input, **mode;
    4437                 :         int chars[256];
    4438               0 :         int ac=ZEND_NUM_ARGS();
    4439               0 :         int mymode=0;
    4440                 :         unsigned char *buf;
    4441                 :         int len, inx;
    4442                 :         char retstr[256];
    4443               0 :         int retlen=0;
    4444                 : 
    4445               0 :         if (ac < 1 || ac > 2 || zend_get_parameters_ex(ac, &input, &mode) == FAILURE) {
    4446               0 :                 WRONG_PARAM_COUNT;
    4447                 :         }
    4448                 :         
    4449               0 :         convert_to_string_ex(input);
    4450                 : 
    4451               0 :         if (ac == 2) {
    4452               0 :                 convert_to_long_ex(mode);
    4453               0 :                 mymode = Z_LVAL_PP(mode);
    4454                 :                 
    4455               0 :                 if (mymode < 0 || mymode > 4) {
    4456               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown mode.");
    4457               0 :                         RETURN_FALSE;
    4458                 :                 }
    4459                 :         }
    4460                 :         
    4461               0 :         len = Z_STRLEN_PP(input);
    4462               0 :         buf = (unsigned char *) Z_STRVAL_PP(input);
    4463               0 :         memset((void*) chars, 0, sizeof(chars));
    4464                 : 
    4465               0 :         while (len > 0) {
    4466               0 :                 chars[*buf]++;
    4467               0 :                 buf++;
    4468               0 :                 len--;
    4469                 :         }
    4470                 : 
    4471               0 :         if (mymode < 3) {
    4472               0 :                 array_init(return_value);
    4473                 :         }
    4474                 : 
    4475               0 :         for (inx = 0; inx < 256; inx++) {
    4476               0 :                 switch (mymode) {
    4477                 :                         case 0:
    4478               0 :                                 add_index_long(return_value, inx, chars[inx]);
    4479               0 :                                 break;
    4480                 :                         case 1:
    4481               0 :                                 if (chars[inx] != 0) {
    4482               0 :                                         add_index_long(return_value, inx, chars[inx]);
    4483                 :                                 }
    4484               0 :                                 break;
    4485                 :                         case 2:
    4486               0 :                                 if (chars[inx] == 0) {
    4487               0 :                                         add_index_long(return_value, inx, chars[inx]);
    4488                 :                                 }
    4489               0 :                                 break;
    4490                 :                         case 3:
    4491               0 :                                 if (chars[inx] != 0) {
    4492               0 :                                         retstr[retlen++] = inx;
    4493                 :                                 }
    4494               0 :                                 break;
    4495                 :                         case 4:
    4496               0 :                                 if (chars[inx] == 0) {
    4497               0 :                                         retstr[retlen++] = inx;
    4498                 :                                 }
    4499                 :                                 break;
    4500                 :                 }
    4501                 :         }
    4502                 :         
    4503               0 :         if (mymode >= 3 && mymode <= 4) {
    4504               0 :                 RETURN_STRINGL(retstr, retlen, 1);
    4505                 :         }
    4506                 : }
    4507                 : /* }}} */
    4508                 : 
    4509                 : /* {{{ php_strnatcmp
    4510                 :  */
    4511                 : static void php_strnatcmp(INTERNAL_FUNCTION_PARAMETERS, int fold_case)
    4512               0 : {
    4513                 :         zval **s1, **s2;
    4514                 : 
    4515               0 :         if (ZEND_NUM_ARGS()!=2 || zend_get_parameters_ex(2, &s1, &s2) == FAILURE) {
    4516               0 :                 WRONG_PARAM_COUNT;
    4517                 :         }
    4518                 : 
    4519               0 :         convert_to_string_ex(s1);
    4520               0 :         convert_to_string_ex(s2);
    4521                 : 
    4522               0 :         RETURN_LONG(strnatcmp_ex(Z_STRVAL_PP(s1), Z_STRLEN_PP(s1),
    4523                 :                                                          Z_STRVAL_PP(s2), Z_STRLEN_PP(s2),
    4524                 :                                                          fold_case));
    4525                 : }
    4526                 : /* }}} */
    4527                 : 
    4528                 : /* {{{ proto int strnatcmp(string s1, string s2)
    4529                 :    Returns the result of string comparison using 'natural' algorithm */
    4530                 : PHP_FUNCTION(strnatcmp)
    4531               0 : {
    4532               0 :         php_strnatcmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    4533               0 : }
    4534                 : /* }}} */
    4535                 : 
    4536                 : /* {{{ proto array localeconv(void)
    4537                 :    Returns numeric formatting information based on the current locale */
    4538                 : PHP_FUNCTION(localeconv)
    4539               0 : {
    4540                 :         zval *grouping, *mon_grouping;
    4541                 :         int len, i;
    4542                 : 
    4543                 :         /* We don't need no stinkin' parameters... */
    4544               0 :         if (ZEND_NUM_ARGS() > 0) {
    4545               0 :                 WRONG_PARAM_COUNT;
    4546                 :         }
    4547                 : 
    4548               0 :         MAKE_STD_ZVAL(grouping);
    4549               0 :         MAKE_STD_ZVAL(mon_grouping);
    4550                 : 
    4551               0 :         array_init(return_value);
    4552               0 :         array_init(grouping);
    4553               0 :         array_init(mon_grouping);
    4554                 : 
    4555                 : #ifdef HAVE_LOCALECONV
    4556                 :         {
    4557                 :                 struct lconv currlocdata;
    4558                 : 
    4559               0 :                 localeconv_r( &currlocdata );
    4560                 :    
    4561                 :                 /* Grab the grouping data out of the array */
    4562               0 :                 len = strlen(currlocdata.grouping);
    4563                 : 
    4564               0 :                 for (i = 0; i < len; i++) {
    4565               0 :                         add_index_long(grouping, i, currlocdata.grouping[i]);
    4566                 :                 }
    4567                 : 
    4568                 :                 /* Grab the monetary grouping data out of the array */
    4569               0 :                 len = strlen(currlocdata.mon_grouping);
    4570                 : 
    4571               0 :                 for (i = 0; i < len; i++) {
    4572               0 :                         add_index_long(mon_grouping, i, currlocdata.mon_grouping[i]);
    4573                 :                 }
    4574                 : 
    4575               0 :                 add_assoc_string(return_value, "decimal_point",     currlocdata.decimal_point,     1);
    4576               0 :                 add_assoc_string(return_value, "thousands_sep",     currlocdata.thousands_sep,     1);
    4577               0 :                 add_assoc_string(return_value, "int_curr_symbol",   currlocdata.int_curr_symbol,   1);
    4578               0 :                 add_assoc_string(return_value, "currency_symbol",   currlocdata.currency_symbol,   1);
    4579               0 :                 add_assoc_string(return_value, "mon_decimal_point", currlocdata.mon_decimal_point, 1);
    4580               0 :                 add_assoc_string(return_value, "mon_thousands_sep", currlocdata.mon_thousands_sep, 1);
    4581               0 :                 add_assoc_string(return_value, "positive_sign",     currlocdata.positive_sign,     1);
    4582               0 :                 add_assoc_string(return_value, "negative_sign",     currlocdata.negative_sign,     1);
    4583               0 :                 add_assoc_long(  return_value, "int_frac_digits",   currlocdata.int_frac_digits     );
    4584               0 :                 add_assoc_long(  return_value, "frac_digits",       currlocdata.frac_digits         );
    4585               0 :                 add_assoc_long(  return_value, "p_cs_precedes",     currlocdata.p_cs_precedes       );
    4586               0 :                 add_assoc_long(  return_value, "p_sep_by_space",    currlocdata.p_sep_by_space      );
    4587               0 :                 add_assoc_long(  return_value, "n_cs_precedes",     currlocdata.n_cs_precedes       );
    4588               0 :                 add_assoc_long(  return_value, "n_sep_by_space",    currlocdata.n_sep_by_space      );
    4589               0 :                 add_assoc_long(  return_value, "p_sign_posn",       currlocdata.p_sign_posn         );
    4590               0 :                 add_assoc_long(  return_value, "n_sign_posn",       currlocdata.n_sign_posn         );
    4591                 :         }
    4592                 : #else
    4593                 :         /* Ok, it doesn't look like we have locale info floating around, so I guess it
    4594                 :            wouldn't hurt to just go ahead and return the POSIX locale information?  */
    4595                 : 
    4596                 :         add_index_long(grouping, 0, -1);
    4597                 :         add_index_long(mon_grouping, 0, -1);
    4598                 : 
    4599                 :         add_assoc_string(return_value, "decimal_point",     "\x2E", 1);
    4600                 :         add_assoc_string(return_value, "thousands_sep",     "",     1);
    4601                 :         add_assoc_string(return_value, "int_curr_symbol",   "",     1);
    4602                 :         add_assoc_string(return_value, "currency_symbol",   "",     1);
    4603                 :         add_assoc_string(return_value, "mon_decimal_point", "\x2E", 1);
    4604                 :         add_assoc_string(return_value, "mon_thousands_sep", "",     1);
    4605                 :         add_assoc_string(return_value, "positive_sign",     "",     1);
    4606                 :         add_assoc_string(return_value, "negative_sign",     "",     1);
    4607                 :         add_assoc_long(  return_value, "int_frac_digits",   CHAR_MAX );
    4608                 :         add_assoc_long(  return_value, "frac_digits",       CHAR_MAX );
    4609                 :         add_assoc_long(  return_value, "p_cs_precedes",     CHAR_MAX );
    4610                 :         add_assoc_long(  return_value, "p_sep_by_space",    CHAR_MAX );
    4611                 :         add_assoc_long(  return_value, "n_cs_precedes",     CHAR_MAX );
    4612                 :         add_assoc_long(  return_value, "n_sep_by_space",    CHAR_MAX );
    4613                 :         add_assoc_long(  return_value, "p_sign_posn",       CHAR_MAX );
    4614                 :         add_assoc_long(  return_value, "n_sign_posn",       CHAR_MAX );
    4615                 : #endif
    4616                 : 
    4617               0 :         zend_hash_update(Z_ARRVAL_P(return_value), "grouping", 9, &grouping, sizeof(zval *), NULL);
    4618               0 :         zend_hash_update(Z_ARRVAL_P(return_value), "mon_grouping", 13, &mon_grouping, sizeof(zval *), NULL);
    4619                 : }
    4620                 : /* }}} */
    4621                 : 
    4622                 : /* {{{ proto int strnatcasecmp(string s1, string s2)
    4623                 :    Returns the result of case-insensitive string comparison using 'natural' algorithm */
    4624                 : PHP_FUNCTION(strnatcasecmp)
    4625               0 : {
    4626               0 :         php_strnatcmp(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    4627               0 : }
    4628                 : /* }}} */
    4629                 : 
    4630                 : /* {{{ proto int substr_count(string haystack, string needle [, int offset [, int length]])
    4631                 :    Returns the number of times a substring occurs in the string */
    4632                 : PHP_FUNCTION(substr_count)
    4633               0 : {
    4634                 :         zval **haystack, **needle, **offset, **length;
    4635               0 :         int ac = ZEND_NUM_ARGS();
    4636               0 :         int count = 0;
    4637                 :         char *p, *endp, cmp;
    4638                 : 
    4639               0 :         if (ac < 2 || ac > 4 || zend_get_parameters_ex(ac, &haystack, &needle, &offset, &length) == FAILURE) {
    4640               0 :                 WRONG_PARAM_COUNT;
    4641                 :         }
    4642                 : 
    4643               0 :         convert_to_string_ex(haystack);
    4644               0 :         convert_to_string_ex(needle);
    4645                 : 
    4646               0 :         if (Z_STRLEN_PP(needle) == 0) {
    4647               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty substring.");
    4648               0 :                 RETURN_FALSE;
    4649                 :         }
    4650                 :         
    4651               0 :         p = Z_STRVAL_PP(haystack);
    4652               0 :         endp = p + Z_STRLEN_PP(haystack);
    4653                 :         
    4654               0 :         if (ac > 2) {
    4655               0 :                 convert_to_long_ex(offset);
    4656               0 :                 if (Z_LVAL_PP(offset) < 0) {
    4657               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset should be greater than or equal to 0.");
    4658               0 :                         RETURN_FALSE;           
    4659                 :                 }
    4660                 : 
    4661               0 :                 if (Z_LVAL_PP(offset) > Z_STRLEN_PP(haystack)) {
    4662               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset value %ld exceeds string length.", Z_LVAL_PP(offset));
    4663               0 :                         RETURN_FALSE;           
    4664                 :                 }
    4665               0 :                 p += Z_LVAL_PP(offset);
    4666                 : 
    4667               0 :                 if (ac == 4) {
    4668               0 :                         convert_to_long_ex(length);
    4669               0 :                         if (Z_LVAL_PP(length) <= 0) {
    4670               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length should be greater than 0.");
    4671               0 :                                 RETURN_FALSE;           
    4672                 :                         }
    4673               0 :                         if (Z_LVAL_PP(length) > (Z_STRLEN_PP(haystack) - Z_LVAL_PP(offset))) {
    4674               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length value %ld exceeds string length.", Z_LVAL_PP(length));
    4675               0 :                                 RETURN_FALSE;
    4676                 :                         }
    4677               0 :                         endp = p + Z_LVAL_PP(length);
    4678                 :                 }
    4679                 :         }
    4680                 :         
    4681               0 :         if (Z_STRLEN_PP(needle) == 1) {
    4682               0 :                 cmp = Z_STRVAL_PP(needle)[0];
    4683                 : 
    4684               0 :                 while ((p = memchr(p, cmp, endp - p))) {
    4685               0 :                         count++;
    4686               0 :                         p++;
    4687                 :                 }
    4688                 :         } else {
    4689               0 :                 while ((p = php_memnstr(p, Z_STRVAL_PP(needle), Z_STRLEN_PP(needle), endp))) {
    4690               0 :                         p += Z_STRLEN_PP(needle);
    4691               0 :                         count++;
    4692                 :                 }
    4693                 :         }
    4694                 : 
    4695               0 :         RETURN_LONG(count);
    4696                 : }
    4697                 : /* }}} */       
    4698                 : 
    4699                 : /* {{{ proto string str_pad(string input, int pad_length [, string pad_string [, int pad_type]])
    4700                 :    Returns input string padded on the left or right to specified length with pad_string */
    4701                 : PHP_FUNCTION(str_pad)
    4702               0 : {
    4703                 :         /* Input arguments */
    4704                 :         zval **input,                           /* Input string */
    4705                 :                  **pad_length,                  /* Length to pad to */
    4706                 :                  **pad_string,                  /* Padding string */
    4707                 :                  **pad_type;                    /* Padding type (left/right/both) */
    4708                 :         
    4709                 :         /* Helper variables */
    4710                 :         int        num_pad_chars;               /* Number of padding characters (total - input size) */
    4711               0 :         char  *result = NULL;           /* Resulting string */
    4712               0 :         int        result_len = 0;              /* Length of the resulting string */
    4713               0 :         char  *pad_str_val = " ";     /* Pointer to padding string */
    4714               0 :         int    pad_str_len = 1;         /* Length of the padding string */
    4715               0 :         int        pad_type_val = STR_PAD_RIGHT; /* The padding type value */
    4716               0 :         int        i, left_pad=0, right_pad=0;
    4717                 : 
    4718                 : 
    4719               0 :         if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 4 ||
    4720                 :                 zend_get_parameters_ex(ZEND_NUM_ARGS(), &input, &pad_length, &pad_string, &pad_type) == FAILURE) {
    4721               0 :                 WRONG_PARAM_COUNT;
    4722                 :         }
    4723                 : 
    4724                 :         /* Perform initial conversion to expected data types. */
    4725               0 :         convert_to_string_ex(input);
    4726               0 :         convert_to_long_ex(pad_length);
    4727                 : 
    4728               0 :         num_pad_chars = Z_LVAL_PP(pad_length) - Z_STRLEN_PP(input);
    4729                 : 
    4730                 :         /* If resulting string turns out to be shorter than input string,
    4731                 :            we simply copy the input and return. */
    4732               0 :         if (num_pad_chars < 0) {
    4733               0 :                 RETURN_ZVAL(*input, 1, 0);
    4734                 :         }
    4735                 : 
    4736                 :         /* Setup the padding string values if specified. */
    4737               0 :         if (ZEND_NUM_ARGS() > 2) {
    4738               0 :                 convert_to_string_ex(pad_string);
    4739               0 :                 if (Z_STRLEN_PP(pad_string) == 0) {
    4740               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Padding string cannot be empty.");
    4741               0 :                         return;
    4742                 :                 }
    4743               0 :                 pad_str_val = Z_STRVAL_PP(pad_string);
    4744               0 :                 pad_str_len = Z_STRLEN_PP(pad_string);
    4745                 : 
    4746               0 :                 if (ZEND_NUM_ARGS() > 3) {
    4747               0 :                         convert_to_long_ex(pad_type);
    4748               0 :                         pad_type_val = Z_LVAL_PP(pad_type);
    4749               0 :                         if (pad_type_val < STR_PAD_LEFT || pad_type_val > STR_PAD_BOTH) {
    4750               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH.");
    4751               0 :                                 return;
    4752                 :                         }
    4753                 :                 }
    4754                 :         }
    4755                 : 
    4756               0 :         result = (char *)emalloc(Z_STRLEN_PP(input) + num_pad_chars + 1);
    4757                 : 
    4758                 :         /* We need to figure out the left/right padding lengths. */
    4759               0 :         switch (pad_type_val) {
    4760                 :                 case STR_PAD_RIGHT:
    4761               0 :                         left_pad = 0;
    4762               0 :                         right_pad = num_pad_chars;
    4763               0 :                         break;
    4764                 : 
    4765                 :                 case STR_PAD_LEFT:
    4766               0 :                         left_pad = num_pad_chars;
    4767               0 :                         right_pad = 0;
    4768               0 :                         break;
    4769                 : 
    4770                 :                 case STR_PAD_BOTH:
    4771               0 :                         left_pad = num_pad_chars / 2;
    4772               0 :                         right_pad = num_pad_chars - left_pad;
    4773                 :                         break;
    4774                 :         }
    4775                 : 
    4776                 :         /* First we pad on the left. */
    4777               0 :         for (i = 0; i < left_pad; i++)
    4778               0 :                 result[result_len++] = pad_str_val[i % pad_str_len];
    4779                 : 
    4780                 :         /* Then we copy the input string. */
    4781               0 :         memcpy(result + result_len, Z_STRVAL_PP(input), Z_STRLEN_PP(input));
    4782               0 :         result_len += Z_STRLEN_PP(input);
    4783                 : 
    4784                 :         /* Finally, we pad on the right. */
    4785               0 :         for (i = 0; i < right_pad; i++)
    4786               0 :                 result[result_len++] = pad_str_val[i % pad_str_len];
    4787                 : 
    4788               0 :         result[result_len] = '\0';
    4789                 : 
    4790               0 :         RETURN_STRINGL(result, result_len, 0);
    4791                 : }
    4792                 : /* }}} */
    4793                 :    
    4794                 : /* {{{ proto mixed sscanf(string str, string format [, string ...])
    4795                 :    Implements an ANSI C compatible sscanf */
    4796                 : PHP_FUNCTION(sscanf)
    4797               0 : {
    4798                 :         zval ***args;
    4799                 :         int     result;
    4800               0 :         int         argc = ZEND_NUM_ARGS();     
    4801                 : 
    4802               0 :         if (argc < 2) {
    4803               0 :                 WRONG_PARAM_COUNT;
    4804                 :         }
    4805                 : 
    4806               0 :         args = (zval ***) safe_emalloc(argc, sizeof(zval **), 0);
    4807               0 :         if (zend_get_parameters_array_ex(argc, args) == FAILURE) {
    4808               0 :                 efree(args);
    4809               0 :                 WRONG_PARAM_COUNT;
    4810                 :         }
    4811                 : 
    4812               0 :         convert_to_string_ex(args[0]);
    4813               0 :         convert_to_string_ex(args[1]);
    4814                 :         
    4815               0 :         result = php_sscanf_internal(Z_STRVAL_PP(args[0]),
    4816                 :                                      Z_STRVAL_PP(args[1]),
    4817                 :                                      argc, args,
    4818                 :                                      2, &return_value TSRMLS_CC);
    4819               0 :         efree(args);
    4820                 : 
    4821               0 :         if (SCAN_ERROR_WRONG_PARAM_COUNT == result) {
    4822               0 :                 WRONG_PARAM_COUNT;
    4823                 :         }
    4824                 : }
    4825                 : /* }}} */
    4826                 : 
    4827                 : static char rot13_from[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    4828                 : static char rot13_to[] = "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM";
    4829                 : 
    4830                 : /* {{{ proto string str_rot13(string str)
    4831                 :    Perform the rot13 transform on a string */
    4832                 : PHP_FUNCTION(str_rot13)
    4833               0 : {
    4834                 :         zval **arg;
    4835                 : 
    4836               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg)) {
    4837               0 :                 WRONG_PARAM_COUNT;
    4838                 :         }
    4839                 : 
    4840               0 :         convert_to_string_ex(arg);
    4841               0 :         RETVAL_ZVAL(*arg, 1, 0);
    4842                 : 
    4843               0 :         php_strtr(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value), rot13_from, rot13_to, 52);
    4844                 : }
    4845                 : /* }}} */
    4846                 : 
    4847                 : 
    4848                 : static void php_string_shuffle(char *str, long len TSRMLS_DC)
    4849               0 : {
    4850                 :         long n_elems, rnd_idx, n_left;
    4851                 :         char temp;
    4852                 :         /* The implementation is stolen from array_data_shuffle       */
    4853                 :         /* Thus the characteristics of the randomization are the same */
    4854               0 :         n_elems = len;
    4855                 :         
    4856               0 :         if (n_elems <= 1) {
    4857               0 :                 return;
    4858                 :         }
    4859                 : 
    4860               0 :         n_left = n_elems;
    4861                 :         
    4862               0 :         while (--n_left) {
    4863               0 :                 rnd_idx = php_rand(TSRMLS_C);
    4864               0 :                 RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX);
    4865               0 :                 if (rnd_idx != n_left) {
    4866               0 :                         temp = str[n_left];
    4867               0 :                         str[n_left] = str[rnd_idx];
    4868               0 :                         str[rnd_idx] = temp;
    4869                 :                 }
    4870                 :         }
    4871                 : }
    4872                 : 
    4873                 : 
    4874                 : /* {{{ proto void str_shuffle(string str)
    4875                 :    Shuffles string. One permutation of all possible is created */
    4876                 : PHP_FUNCTION(str_shuffle)
    4877               0 : {
    4878                 :         zval **arg;
    4879                 :         
    4880               0 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg)) {
    4881               0 :                 WRONG_PARAM_COUNT;
    4882                 :         }
    4883                 :         
    4884               0 :         convert_to_string_ex(arg);
    4885               0 :         RETVAL_ZVAL(*arg, 1, 0);
    4886               0 :         if (Z_STRLEN_P(return_value) > 1) { 
    4887               0 :                 php_string_shuffle(Z_STRVAL_P(return_value), (long) Z_STRLEN_P(return_value) TSRMLS_CC);
    4888                 :         }
    4889                 : }
    4890                 : /* }}} */
    4891                 : 
    4892                 : /* {{{ proto mixed str_word_count(string str, [int format [, string charlist]])
    4893                 :         Counts the number of words inside a string. If format of 1 is specified,
    4894                 :         then the function will return an array containing all the words
    4895                 :         found inside the string. If format of 2 is specified, then the function
    4896                 :         will return an associated array where the position of the word is the key
    4897                 :         and the word itself is the value.
    4898                 :         
    4899                 :         For the purpose of this function, 'word' is defined as a locale dependent
    4900                 :         string containing alphabetic characters, which also may contain, but not start
    4901                 :         with "'" and "-" characters.
    4902                 : */
    4903                 : PHP_FUNCTION(str_word_count)
    4904               0 : {
    4905               0 :         char *buf, *str, *char_list = NULL, *p, *e, *s, ch[256];
    4906               0 :         int str_len, char_list_len, word_count = 0;
    4907               0 :         long type = 0;
    4908                 : 
    4909               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ls", &str, &str_len, &type, &char_list, &char_list_len) == FAILURE) {
    4910               0 :                 return;
    4911                 :         }
    4912                 : 
    4913               0 :         switch(type) {
    4914                 :                 case 1:
    4915                 :                 case 2:
    4916               0 :                         array_init(return_value);
    4917               0 :                         if (!str_len) {
    4918               0 :                                 return;
    4919                 :                         }
    4920               0 :                         break;
    4921                 :                 case 0:
    4922               0 :                         if (!str_len) {
    4923               0 :                                 RETURN_LONG(0);
    4924                 :                         }
    4925                 :                         /* nothing to be done */
    4926               0 :                         break;
    4927                 :                 default:
    4928               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid format value %ld", type);
    4929               0 :                         RETURN_FALSE;
    4930                 :         }
    4931                 : 
    4932               0 :         if (char_list) {
    4933               0 :                 php_charmask(char_list, char_list_len, ch TSRMLS_CC);
    4934                 :         }
    4935                 :         
    4936               0 :         p = str;
    4937               0 :         e = str + str_len;
    4938                 : 
    4939                 :         /* first character cannot be ' or -, unless explicitly allowed by the user */
    4940               0 :         if ((*p == '\'' && (!char_list || !ch['\''])) || (*p == '-' && (!char_list || !ch['-']))) {
    4941               0 :                 p++;
    4942                 :         }
    4943                 :         /* last character cannot be -, unless explicitly allowed by the user */
    4944               0 :         if (*(e - 1) == '-' && (!char_list || !ch['-'])) {
    4945               0 :                 e--;
    4946                 :         }
    4947                 : 
    4948               0 :         while (p < e) {
    4949               0 :                 s = p;
    4950               0 :                 while (p < e && (isalpha(*p) || (char_list && ch[(unsigned char)*p]) || *p == '\'' || *p == '-')) {
    4951               0 :                         p++;
    4952                 :                 }
    4953               0 :                 if (p > s) {
    4954               0 :                         switch (type)
    4955                 :                         {
    4956                 :                                 case 1:
    4957               0 :                                         buf = estrndup(s, (p-s));
    4958               0 :                                         add_next_index_stringl(return_value, buf, (p-s), 0);
    4959               0 :                                         break;
    4960                 :                                 case 2:
    4961               0 :                                         buf = estrndup(s, (p-s));
    4962               0 :                                         add_index_stringl(return_value, (s - str), buf, p-s, 0);
    4963               0 :                                         break;
    4964                 :                                 default:
    4965               0 :                                         word_count++;
    4966                 :                                         break;          
    4967                 :                         }
    4968                 :                 }
    4969               0 :                 p++;
    4970                 :         }
    4971                 :         
    4972               0 :         if (!type) {
    4973               0 :                 RETURN_LONG(word_count);                
    4974                 :         }
    4975                 : }
    4976                 : 
    4977                 : /* }}} */
    4978                 : 
    4979                 : #if HAVE_STRFMON
    4980                 : /* {{{ proto string money_format(string format , float value)
    4981                 :    Convert monetary value(s) to string */
    4982                 : PHP_FUNCTION(money_format)
    4983               0 : {
    4984               0 :         int format_len = 0, str_len;
    4985                 :         char *format, *str;
    4986                 :         double value;
    4987                 : 
    4988               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sd", &format, &format_len, &value) == FAILURE) {
    4989               0 :                 return;
    4990                 :         }
    4991                 : 
    4992               0 :         str_len = format_len + 1024;
    4993               0 :         str = emalloc(str_len);
    4994               0 :         if ((str_len = strfmon(str, str_len, format, value)) < 0) {
    4995               0 :                 efree(str);
    4996               0 :                 RETURN_FALSE;
    4997                 :         }
    4998               0 :         str[str_len] = 0;
    4999                 : 
    5000               0 :         RETURN_STRINGL(erealloc(str, str_len + 1), str_len, 0);
    5001                 : }
    5002                 : /* }}} */
    5003                 : #endif
    5004                 : 
    5005                 : /* {{{ proto array str_split(string str [, int split_length])
    5006                 :    Convert a string to an array. If split_length is specified, break the string down into chunks each split_length characters long. */
    5007                 : PHP_FUNCTION(str_split)
    5008               1 : {
    5009                 :         char *str;
    5010                 :         int str_len;
    5011               1 :         long split_length = 1;
    5012                 :         char *p;
    5013                 :         int n_reg_segments;
    5014                 :         
    5015               1 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &str, &str_len, &split_length) == FAILURE) {
    5016               0 :                 return;
    5017                 :         }
    5018                 : 
    5019               1 :         if (split_length <= 0) {
    5020               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The length of each segment must be greater than zero.");
    5021               0 :                 RETURN_FALSE;
    5022                 :         }
    5023                 : 
    5024               1 :         array_init(return_value);
    5025                 : 
    5026               1 :         if (split_length >= str_len) {
    5027               0 :                 add_next_index_stringl(return_value, str, str_len, 1);
    5028               0 :                 return;
    5029                 :         }
    5030                 : 
    5031               1 :         n_reg_segments = floor(str_len / split_length);
    5032               1 :         p = str;
    5033                 : 
    5034              34 :         while (n_reg_segments-- > 0) {
    5035              32 :                 add_next_index_stringl(return_value, p, split_length, 1);
    5036              32 :                 p += split_length;
    5037                 :         }
    5038                 : 
    5039               1 :         if (p != (str + str_len)) {
    5040               0 :                 add_next_index_stringl(return_value, p, (str + str_len - p), 1);
    5041                 :         }
    5042                 : }
    5043                 : /* }}} */
    5044                 : 
    5045                 : /* {{{ proto array strpbrk(string haystack, string char_list)
    5046                 :    Search a string for any of a set of characters */
    5047                 : PHP_FUNCTION(strpbrk)
    5048               0 : {
    5049                 :         char *haystack, *char_list;
    5050                 :         int haystack_len, char_list_len;
    5051                 :         char *p;
    5052                 :         
    5053               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &haystack, &haystack_len, &char_list, &char_list_len) == FAILURE) {
    5054               0 :                 RETURN_FALSE;
    5055                 :         }
    5056                 : 
    5057               0 :         if (!char_list_len) {
    5058               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The character list cannot be empty.");
    5059               0 :                 RETURN_FALSE;   
    5060                 :         }
    5061                 : 
    5062               0 :         if ((p = strpbrk(haystack, char_list))) {
    5063               0 :                 RETURN_STRINGL(p, (haystack + haystack_len - p), 1);
    5064                 :         } else {
    5065               0 :                 RETURN_FALSE;
    5066                 :         }
    5067                 : }
    5068                 : /* }}} */
    5069                 : 
    5070                 : /* {{{ proto int substr_compare(string main_str, string str, int offset [, int length [, bool case_sensitivity]])
    5071                 :    Binary safe optionally case insensitive comparison of 2 strings from an offset, up to length characters */
    5072                 : PHP_FUNCTION(substr_compare)
    5073               0 : {
    5074                 :         char *s1, *s2;
    5075                 :         int s1_len, s2_len;
    5076               0 :         long offset, len=0;
    5077               0 :         zend_bool cs=0;
    5078                 :         uint cmp_len;
    5079                 : 
    5080               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssl|lb", &s1, &s1_len, &s2, &s2_len, &offset, &len, &cs) == FAILURE) {
    5081               0 :                 RETURN_FALSE;
    5082                 :         }
    5083                 : 
    5084               0 :         if (ZEND_NUM_ARGS() >= 4 && len <= 0) {
    5085               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The length must be greater than zero");
    5086               0 :                 RETURN_FALSE;
    5087                 :         }
    5088                 : 
    5089               0 :         if (offset < 0) {
    5090               0 :                 offset = s1_len + offset;
    5091               0 :                 offset = (offset < 0) ? 0 : offset;
    5092                 :         }
    5093                 : 
    5094               0 :         if(offset > s1_len) {
    5095               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The start position cannot exceed initial string length");
    5096               0 :                 RETURN_FALSE;
    5097                 :         }
    5098                 : 
    5099               0 :         if(len > s1_len - offset) {
    5100               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The length cannot exceed initial string length");
    5101               0 :                 RETURN_FALSE;
    5102                 :         }
    5103                 : 
    5104               0 :         cmp_len = (uint) (len ? len : MAX(s2_len, (s1_len - offset)));
    5105                 : 
    5106               0 :         if (!cs) {
    5107               0 :                 RETURN_LONG(zend_binary_strncmp(s1 + offset, (s1_len - offset), s2, s2_len, cmp_len));
    5108                 :         } else {
    5109               0 :                 RETURN_LONG(zend_binary_strncasecmp(s1 + offset, (s1_len - offset), s2, s2_len, cmp_len));
    5110                 :         }
    5111                 : }
    5112                 : /* }}} */
    5113                 : 
    5114                 : /*
    5115                 :  * Local variables:
    5116                 :  * tab-width: 4
    5117                 :  * c-basic-offset: 4
    5118                 :  * End:
    5119                 :  * vim600: noet sw=4 ts=4 fdm=marker
    5120                 :  * vim<600: noet sw=4 ts=4
    5121                 :  */

Generated by: LTP GCOV extension version 1.5