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

LTP GCOV extension - code coverage report
Current view: directory - standard - string.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 2345
Code covered: 95.4 % Executed lines: 2238
Legend: not executed executed

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