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

LCOV - code coverage report
Current view: top level - ext/standard - string.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 2296 2423 94.8 %
Date: 2014-07-23 Functions: 107 107 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Wed, 23 Jul 2014 19:58:40 +0000 (43 hours ago)

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