Annotation of embedaddon/php/ext/standard/string.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>