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: 0 2548 0.0 %
Date: 2014-04-16 Functions: 0 119 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Wed, 16 Apr 2014 12:47:58 +0000 (8 days ago)

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