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

LCOV - code coverage report
Current view: top level - ext/ereg - ereg.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 259 300 86.3 %
Date: 2014-09-19 Functions: 17 19 89.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
      16             :    |          Jim Winstead <jimw@php.net>                                 |
      17             :    |          Jaakko Hyvätti <jaakko@hyvatti.iki.fi>                      | 
      18             :    +----------------------------------------------------------------------+
      19             :  */
      20             : /* $Id$ */
      21             : 
      22             : #include <stdio.h>
      23             : #include <ctype.h>
      24             : #include "php.h"
      25             : #include "ext/standard/php_string.h"
      26             : #include "php_ereg.h"
      27             : #include "ext/standard/info.h"
      28             : 
      29             : /* {{{ arginfo */
      30             : ZEND_BEGIN_ARG_INFO_EX(arginfo_ereg, 0, 0, 2)
      31             :         ZEND_ARG_INFO(0, pattern)
      32             :         ZEND_ARG_INFO(0, string) 
      33             :         ZEND_ARG_INFO(1, registers) /* ARRAY_INFO(1, registers, 1) */
      34             : ZEND_END_ARG_INFO()
      35             : 
      36             : ZEND_BEGIN_ARG_INFO(arginfo_ereg_replace, 0)
      37             :         ZEND_ARG_INFO(0, pattern)
      38             :         ZEND_ARG_INFO(0, replacement)
      39             :         ZEND_ARG_INFO(0, string)
      40             : ZEND_END_ARG_INFO()
      41             : 
      42             : ZEND_BEGIN_ARG_INFO_EX(arginfo_split, 0, 0, 2)
      43             :         ZEND_ARG_INFO(0, pattern)
      44             :         ZEND_ARG_INFO(0, string) 
      45             :         ZEND_ARG_INFO(0, limit)  
      46             : ZEND_END_ARG_INFO()
      47             : 
      48             : ZEND_BEGIN_ARG_INFO(arginfo_sql_regcase, 0)
      49             :         ZEND_ARG_INFO(0, string)
      50             : ZEND_END_ARG_INFO()
      51             : /* }}} */
      52             : 
      53             : /* {{{ Function table */
      54             : const zend_function_entry ereg_functions[] = {
      55             :         PHP_DEP_FE(ereg,                        arginfo_ereg)
      56             :         PHP_DEP_FE(ereg_replace,        arginfo_ereg_replace)
      57             :         PHP_DEP_FE(eregi,                       arginfo_ereg)
      58             :         PHP_DEP_FE(eregi_replace,       arginfo_ereg_replace)
      59             :         PHP_DEP_FE(split,                       arginfo_split)
      60             :         PHP_DEP_FE(spliti,                      arginfo_split)
      61             :         PHP_DEP_FE(sql_regcase,         arginfo_sql_regcase)
      62             :         PHP_FE_END
      63             : };
      64             : /* }}} */
      65             : 
      66             : /* {{{ reg_cache */
      67             : typedef struct {
      68             :         regex_t preg;
      69             :         int cflags;
      70             :         unsigned long lastuse;
      71             : } reg_cache;
      72             : static int reg_magic = 0;
      73             : #define EREG_CACHE_SIZE 4096
      74             : /* }}} */
      75             : 
      76             : ZEND_DECLARE_MODULE_GLOBALS(ereg)
      77             : static PHP_GINIT_FUNCTION(ereg);
      78             : static PHP_GSHUTDOWN_FUNCTION(ereg);
      79             : 
      80             : /* {{{ Module entry */
      81             : zend_module_entry ereg_module_entry = {
      82             :         STANDARD_MODULE_HEADER,
      83             :         "ereg",
      84             :         ereg_functions,
      85             :         NULL,
      86             :         NULL,
      87             :         NULL,
      88             :         NULL,
      89             :         PHP_MINFO(ereg),
      90             :         NO_VERSION_YET,
      91             :         PHP_MODULE_GLOBALS(ereg),
      92             :         PHP_GINIT(ereg),
      93             :         PHP_GSHUTDOWN(ereg),
      94             :         NULL,
      95             :         STANDARD_MODULE_PROPERTIES_EX
      96             : };
      97             : /* }}} */
      98             : 
      99             : /* {{{ COMPILE_DL_EREG */
     100             : #ifdef COMPILE_DL_EREG
     101             : ZEND_GET_MODULE(ereg)
     102             : #endif
     103             : /* }}} */
     104             : 
     105             : /* {{{ ereg_lru_cmp */
     106           0 : static int ereg_lru_cmp(const void *a, const void *b TSRMLS_DC)
     107             : {
     108           0 :         Bucket *f = (Bucket *) a;
     109           0 :         Bucket *s = (Bucket *) b;
     110             : 
     111           0 :         if (((reg_cache *)Z_PTR(f->val))->lastuse <
     112           0 :                                 ((reg_cache *)Z_PTR(s->val))->lastuse) {
     113           0 :                 return -1;
     114           0 :         } else if (((reg_cache *)Z_PTR(f->val))->lastuse ==
     115           0 :                                 ((reg_cache *)Z_PTR(s->val))->lastuse) {
     116           0 :                 return 0;
     117             :         } else {
     118           0 :                 return 1;
     119             :         }
     120             : }
     121             : /* }}} */
     122             : 
     123             : /* {{{ static ereg_clean_cache */
     124           0 : static int ereg_clean_cache(zval *data, void *arg TSRMLS_DC)
     125             : {
     126           0 :         int *num_clean = (int *)arg;
     127             : 
     128           0 :         if (*num_clean > 0) {
     129           0 :                 (*num_clean)--;
     130           0 :                 return ZEND_HASH_APPLY_REMOVE;
     131             :         } else {
     132           0 :                 return ZEND_HASH_APPLY_STOP;
     133             :         }
     134             : }
     135             : /* }}} */
     136             : 
     137             : /* {{{ _php_regcomp
     138             :  */
     139         666 : static int _php_regcomp(regex_t *preg, const char *pattern, int cflags TSRMLS_DC)
     140             : {
     141         666 :         int r = 0;
     142         666 :         int patlen = strlen(pattern);
     143         666 :         reg_cache *rc = NULL;
     144             : 
     145         666 :         if (zend_hash_num_elements(&EREG(ht_rc)) >= EREG_CACHE_SIZE) {
     146             :                 /* easier than dealing with overflow as it happens */
     147           0 :                 if (EREG(lru_counter) >= (1 << 31) || zend_hash_sort(&EREG(ht_rc), zend_qsort, ereg_lru_cmp, 0 TSRMLS_CC) == FAILURE) {
     148           0 :                         zend_hash_clean(&EREG(ht_rc));
     149           0 :                         EREG(lru_counter) = 0;
     150             :                 } else {
     151           0 :                         int num_clean = EREG_CACHE_SIZE / 4;
     152           0 :                         zend_hash_apply_with_argument(&EREG(ht_rc), ereg_clean_cache, &num_clean TSRMLS_CC);
     153             :                 }
     154             :         }
     155             : 
     156         666 :         rc = zend_hash_str_find_ptr(&EREG(ht_rc), pattern, patlen);
     157         941 :         if (rc
     158         275 :            && rc->cflags == cflags) {
     159             : #ifdef HAVE_REGEX_T_RE_MAGIC
     160             :                 /*
     161             :                  * We use a saved magic number to see whether cache is corrupted, and if it
     162             :                  * is, we flush it and compile the pattern from scratch.
     163             :                  */
     164         273 :                 if (rc->preg.re_magic != reg_magic) {
     165           0 :                         zend_hash_clean(&EREG(ht_rc));
     166           0 :                         EREG(lru_counter) = 0;
     167             :                 } else {
     168         273 :                         memcpy(preg, &rc->preg, sizeof(*preg));
     169         273 :                         return r;
     170             :                 }
     171             :         }
     172             : 
     173         393 :         r = regcomp(preg, pattern, cflags);
     174         393 :         if(!r) {
     175             :                 reg_cache rcp;
     176             : 
     177         251 :                 rcp.cflags = cflags;
     178         251 :                 rcp.lastuse = ++(EREG(lru_counter));
     179         251 :                 memcpy(&rcp.preg, preg, sizeof(*preg));
     180             :                 /*
     181             :                  * Since we don't have access to the actual MAGIC1 definition in the private
     182             :                  * header file, we save the magic value immediately after compilation. Hopefully,
     183             :                  * it's good.
     184             :                  */
     185         251 :                 if (!reg_magic) reg_magic = preg->re_magic;
     186         251 :                 zend_hash_str_update_mem(&EREG(ht_rc), pattern, patlen,
     187             :                         &rcp, sizeof(rcp));
     188             :         }
     189             : #else
     190             :                 memcpy(preg, &rc->preg, sizeof(*preg));
     191             :         } else {
     192             :                 r = regcomp(preg, pattern, cflags);
     193             :                 if(!r) {
     194             :                         reg_cache rcp;
     195             : 
     196             :                         rcp.cflags = cflags;
     197             :                         rcp.lastuse = ++(EREG(lru_counter));
     198             :                         memcpy(&rcp.preg, preg, sizeof(*preg));
     199             :                         zend_hash_str_update_mem(&EREG(ht_rc), pattern, patlen,
     200             :                                 &rcp, sizeof(rcp));
     201             :                 }
     202             :         }
     203             : #endif
     204         393 :         return r;
     205             : }
     206             : /* }}} */
     207             : 
     208         251 : static void _free_ereg_cache(zval *zv)
     209             : {
     210         251 :         reg_cache *rc = Z_PTR_P(zv);
     211         251 :         regfree(&rc->preg);
     212         251 :         free(rc);
     213         251 : }
     214             : 
     215             : #undef regfree
     216             : #define regfree(a);
     217             : #undef regcomp
     218             : #define regcomp(a, b, c) _php_regcomp(a, b, c TSRMLS_CC)
     219             : 
     220             : /* {{{ PHP_GINIT_FUNCTION
     221             :  */
     222       20335 : static PHP_GINIT_FUNCTION(ereg)
     223             : {
     224       20335 :         zend_hash_init(&ereg_globals->ht_rc, 0, NULL, _free_ereg_cache, 1);
     225       20335 :         ereg_globals->lru_counter = 0;
     226       20335 : }
     227             : /* }}} */
     228             : 
     229             : /* {{{ PHP_GSHUTDOWN_FUNCTION
     230             :  */
     231       20369 : static PHP_GSHUTDOWN_FUNCTION(ereg)
     232             : {
     233       20369 :         zend_hash_destroy(&ereg_globals->ht_rc);
     234       20369 : }
     235             : /* }}} */
     236             : 
     237         143 : PHP_MINFO_FUNCTION(ereg)
     238             : {
     239         143 :         php_info_print_table_start();
     240             : #if HSREGEX
     241         143 :         php_info_print_table_row(2, "Regex Library", "Bundled library enabled");
     242             : #else
     243             :         php_info_print_table_row(2, "Regex Library", "System library enabled");
     244             : #endif
     245         143 :         php_info_print_table_end();
     246         143 : }
     247             : 
     248             : 
     249             : /* {{{ php_ereg_eprint
     250             :  * php_ereg_eprint - convert error number to name
     251             :  */
     252         142 : static void php_ereg_eprint(int err, regex_t *re TSRMLS_DC) {
     253         142 :         char *buf = NULL, *message = NULL;
     254             :         size_t len;
     255             :         size_t buf_len;
     256             : 
     257             : #ifdef REG_ITOA
     258             :         /* get the length of the message */
     259         142 :         buf_len = regerror(REG_ITOA | err, re, NULL, 0);
     260         142 :         if (buf_len) {
     261         142 :                 buf = (char *)safe_emalloc(buf_len, sizeof(char), 0);
     262         142 :                 if (!buf) return; /* fail silently */
     263             :                 /* finally, get the error message */
     264         142 :                 regerror(REG_ITOA | err, re, buf, buf_len);
     265             :         }
     266             : #else
     267             :         buf_len = 0;
     268             : #endif
     269         142 :         len = regerror(err, re, NULL, 0);
     270         142 :         if (len) {
     271         142 :                 message = (char *)safe_emalloc((buf_len + len + 2), sizeof(char), 0);
     272         142 :                 if (!message) {
     273           0 :                         return; /* fail silently */
     274             :                 }
     275         142 :                 if (buf_len) {
     276         142 :                         snprintf(message, buf_len, "%s: ", buf);
     277         142 :                         buf_len += 1; /* so pointer math below works */
     278             :                 }
     279             :                 /* drop the message into place */
     280         142 :                 regerror(err, re, message + buf_len, len);
     281             : 
     282         142 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message);
     283             :         }
     284             : 
     285         142 :         if (buf) efree(buf);
     286         142 :         if (message) efree(message);
     287             : }
     288             : /* }}} */
     289             : 
     290             : /* {{{ php_ereg
     291             :  */
     292         253 : static void php_ereg(INTERNAL_FUNCTION_PARAMETERS, int icase)
     293             : {
     294             :         zval *regex,                    /* Regular expression */
     295         253 :                 *array = NULL;          /* Optional register array */
     296             :         char *findin;           /* String to apply expression to */
     297             :         size_t findin_len;
     298             :         regex_t re;
     299             :         regmatch_t *subs;
     300             :         int err, match_len, string_len;
     301             :         uint i;
     302         253 :         int copts = 0;
     303             :         off_t start, end;
     304         253 :         char *buf = NULL;
     305         253 :         char *string = NULL;
     306         253 :         int   argc = ZEND_NUM_ARGS();
     307             : 
     308         253 :         if (zend_parse_parameters(argc TSRMLS_CC, "zs|z/", &regex, &findin, &findin_len, &array) == FAILURE) {
     309          16 :                 return;
     310             :         }
     311             : 
     312         237 :         if (icase) {
     313         117 :                 copts |= REG_ICASE;
     314             :         }
     315             :         
     316         237 :         if (argc == 2) {
     317          57 :                 copts |= REG_NOSUB;
     318             :         }
     319             : 
     320             :         /* compile the regular expression from the supplied regex */
     321         237 :         if (Z_TYPE_P(regex) == IS_STRING) {
     322         191 :                 err = regcomp(&re, Z_STRVAL_P(regex), REG_EXTENDED | copts);
     323             :         } else {
     324             :                 /* we convert numbers to integers and treat them as a string */
     325          46 :                 if (Z_TYPE_P(regex) == IS_DOUBLE) {
     326          10 :                         convert_to_long_ex(regex);      /* get rid of decimal places */
     327             :                 }
     328          66 :                 convert_to_string_ex(regex);
     329             :                 /* don't bother doing an extended regex with just a number */
     330          46 :                 err = regcomp(&re, Z_STRVAL_P(regex), copts);
     331             :         }
     332             : 
     333         237 :         if (err) {
     334          46 :                 php_ereg_eprint(err, &re TSRMLS_CC);
     335          46 :                 RETURN_FALSE;
     336             :         }
     337             : 
     338             :         /* make a copy of the string we're looking in */
     339         191 :         string = estrndup(findin, findin_len);
     340             : 
     341             :         /* allocate storage for (sub-)expression-matches */
     342         191 :         subs = (regmatch_t *)ecalloc(sizeof(regmatch_t),re.re_nsub+1);
     343             :         
     344             :         /* actually execute the regular expression */
     345         191 :         err = regexec(&re, string, re.re_nsub+1, subs, 0);
     346         191 :         if (err && err != REG_NOMATCH) {
     347           0 :                 php_ereg_eprint(err, &re TSRMLS_CC);
     348             :                 regfree(&re);
     349           0 :                 efree(subs);
     350           0 :                 RETURN_FALSE;
     351             :         }
     352         191 :         match_len = 1;
     353             : 
     354         191 :         if (array && err != REG_NOMATCH) {
     355          99 :                 match_len = (int) (subs[0].rm_eo - subs[0].rm_so);
     356          99 :                 string_len = findin_len + 1;
     357             : 
     358          99 :                 buf = emalloc(string_len);
     359             : 
     360          99 :                 zval_dtor(array);       /* start with clean array */
     361          99 :                 array_init(array);
     362             : 
     363        4358 :                 for (i = 0; i <= re.re_nsub; i++) {
     364        4259 :                         start = subs[i].rm_so;
     365        4259 :                         end = subs[i].rm_eo;
     366        8510 :                         if (start != -1 && end > 0 && start < string_len && end < string_len && start < end) {
     367        4251 :                                 add_index_stringl(array, i, string+start, end-start);
     368             :                         } else {
     369           8 :                                 add_index_bool(array, i, 0);
     370             :                         }
     371             :                 }
     372          99 :                 efree(buf);
     373             :         }
     374             : 
     375         191 :         efree(subs);
     376         191 :         efree(string);
     377         191 :         if (err == REG_NOMATCH) {
     378          63 :                 RETVAL_FALSE;
     379             :         } else {
     380         128 :                 if (match_len == 0)
     381           4 :                         match_len = 1;
     382         128 :                 RETVAL_LONG(match_len);
     383             :         }
     384             :         regfree(&re);
     385             : }
     386             : /* }}} */
     387             : 
     388             : /* {{{ proto int ereg(string pattern, string string [, array registers])
     389             :    Regular expression match */
     390         128 : PHP_FUNCTION(ereg)
     391             : {
     392         128 :         php_ereg(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
     393         128 : }
     394             : /* }}} */
     395             : 
     396             : /* {{{ proto int eregi(string pattern, string string [, array registers])
     397             :    Case-insensitive regular expression match */
     398         125 : PHP_FUNCTION(eregi)
     399             : {
     400         125 :         php_ereg(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     401         125 : }
     402             : /* }}} */
     403             : 
     404             : /* {{{ php_ereg_replace
     405             :  * this is the meat and potatoes of regex replacement! */
     406         222 : PHP_EREG_API char *php_ereg_replace(const char *pattern, const char *replace, const char *string, int icase, int extended TSRMLS_DC)
     407             : {
     408             :         regex_t re;
     409             :         regmatch_t *subs;
     410             : 
     411             :         char *buf,      /* buf is where we build the replaced string */
     412             :                  *nbuf, /* nbuf is used when we grow the buffer */
     413             :                  *walkbuf; /* used to walk buf when replacing backrefs */
     414             :         const char *walk; /* used to walk replacement string for backrefs */
     415             :         int buf_len;
     416             :         int pos, tmp, string_len, new_l;
     417         222 :         int err, copts = 0;
     418             : 
     419         222 :         string_len = strlen(string);
     420             : 
     421         222 :         if (icase) {
     422         103 :                 copts = REG_ICASE;
     423             :         }
     424         222 :         if (extended) {
     425         222 :                 copts |= REG_EXTENDED;
     426             :         }
     427             : 
     428         222 :         err = regcomp(&re, pattern, copts);
     429         222 :         if (err) {
     430          54 :                 php_ereg_eprint(err, &re TSRMLS_CC);
     431          54 :                 return ((char *) -1);
     432             :         }
     433             : 
     434             : 
     435             :         /* allocate storage for (sub-)expression-matches */
     436         168 :         subs = (regmatch_t *)ecalloc(sizeof(regmatch_t),re.re_nsub+1);
     437             : 
     438             :         /* start with a buffer that is twice the size of the stringo
     439             :            we're doing replacements in */
     440         168 :         buf_len = 2 * string_len + 1;
     441         168 :         buf = safe_emalloc(buf_len, sizeof(char), 0);
     442             : 
     443         168 :         err = pos = 0;
     444         168 :         buf[0] = '\0';
     445         865 :         while (!err) {
     446         536 :                 err = regexec(&re, &string[pos], re.re_nsub+1, subs, (pos ? REG_NOTBOL : 0));
     447             : 
     448         536 :                 if (err && err != REG_NOMATCH) {
     449           0 :                         php_ereg_eprint(err, &re TSRMLS_CC);
     450           0 :                         efree(subs);
     451           0 :                         efree(buf);
     452             :                         regfree(&re);
     453           0 :                         return ((char *) -1);
     454             :                 }
     455             : 
     456         536 :                 if (!err) {
     457             :                         /* backref replacement is done in two passes:
     458             :                            1) find out how long the string will be, and allocate buf
     459             :                            2) copy the part before match, replacement and backrefs to buf
     460             : 
     461             :                            Jaakko Hyvätti <Jaakko.Hyvatti@iki.fi>
     462             :                            */
     463             : 
     464         375 :                         new_l = strlen(buf) + subs[0].rm_so; /* part before the match */
     465         375 :                         walk = replace;
     466        7533 :                         while (*walk) {
     467        6793 :                                 if ('\\' == *walk && isdigit((unsigned char)walk[1]) && ((unsigned char)walk[1]) - '0' <= (int)re.re_nsub) {
     468          10 :                                         if (subs[walk[1] - '0'].rm_so > -1 && subs[walk[1] - '0'].rm_eo > -1) {
     469          10 :                                                 new_l += subs[walk[1] - '0'].rm_eo - subs[walk[1] - '0'].rm_so;
     470             :                                         }
     471          10 :                                         walk += 2;
     472             :                                 } else {
     473        6773 :                                         new_l++;
     474        6773 :                                         walk++;
     475             :                                 }
     476             :                         }
     477         375 :                         if (new_l + 1 > buf_len) {
     478          37 :                                 buf_len = 1 + buf_len + 2 * new_l;
     479          37 :                                 nbuf = emalloc(buf_len);
     480          37 :                                 strncpy(nbuf, buf, buf_len - 1);
     481          37 :                                 nbuf[buf_len - 1] = '\0';
     482          37 :                                 efree(buf);
     483          37 :                                 buf = nbuf;
     484             :                         }
     485         375 :                         tmp = strlen(buf);
     486             :                         /* copy the part of the string before the match */
     487         375 :                         strncat(buf, &string[pos], subs[0].rm_so);
     488             : 
     489             :                         /* copy replacement and backrefs */
     490         375 :                         walkbuf = &buf[tmp + subs[0].rm_so];
     491         375 :                         walk = replace;
     492        7533 :                         while (*walk) {
     493        6793 :                                 if ('\\' == *walk && isdigit((unsigned char)walk[1]) && (unsigned char)walk[1] - '0' <= (int)re.re_nsub) {
     494          30 :                                         if (subs[walk[1] - '0'].rm_so > -1 && subs[walk[1] - '0'].rm_eo > -1
     495             :                                                 /* this next case shouldn't happen. it does. */
     496          20 :                                                 && subs[walk[1] - '0'].rm_so <= subs[walk[1] - '0'].rm_eo) {
     497             :                                                 
     498          10 :                                                 tmp = subs[walk[1] - '0'].rm_eo - subs[walk[1] - '0'].rm_so;
     499          10 :                                                 memcpy (walkbuf, &string[pos + subs[walk[1] - '0'].rm_so], tmp);
     500          10 :                                                 walkbuf += tmp;
     501             :                                         }
     502          10 :                                         walk += 2;
     503             :                                 } else {
     504        6773 :                                         *walkbuf++ = *walk++;
     505             :                                 }
     506             :                         }
     507         375 :                         *walkbuf = '\0';
     508             : 
     509             :                         /* and get ready to keep looking for replacements */
     510         375 :                         if (subs[0].rm_so == subs[0].rm_eo) {
     511         144 :                                 if (subs[0].rm_so + pos >= string_len) {
     512           7 :                                         break;
     513             :                                 }
     514         137 :                                 new_l = strlen (buf) + 1;
     515         137 :                                 if (new_l + 1 > buf_len) {
     516           0 :                                         buf_len = 1 + buf_len + 2 * new_l;
     517           0 :                                         nbuf = safe_emalloc(buf_len, sizeof(char), 0);
     518           0 :                                         strncpy(nbuf, buf, buf_len-1);
     519           0 :                                         efree(buf);
     520           0 :                                         buf = nbuf;
     521             :                                 }
     522         137 :                                 pos += subs[0].rm_eo + 1;
     523         137 :                                 buf [new_l-1] = string [pos-1];
     524         137 :                                 buf [new_l] = '\0';
     525             :                         } else {
     526         231 :                                 pos += subs[0].rm_eo;
     527             :                         }
     528             :                 } else { /* REG_NOMATCH */
     529         161 :                         new_l = strlen(buf) + strlen(&string[pos]);
     530         161 :                         if (new_l + 1 > buf_len) {
     531           8 :                                 buf_len = new_l + 1; /* now we know exactly how long it is */
     532           8 :                                 nbuf = safe_emalloc(buf_len, sizeof(char), 0);
     533           8 :                                 strncpy(nbuf, buf, buf_len-1);
     534           8 :                                 efree(buf);
     535           8 :                                 buf = nbuf;
     536             :                         }
     537             :                         /* stick that last bit of string on our output */
     538         161 :                         strlcat(buf, &string[pos], buf_len);
     539             :                 }
     540             :         }
     541             : 
     542             :         /* don't want to leak memory .. */
     543         168 :         efree(subs);
     544             :         regfree(&re);
     545             : 
     546             :         /* whew. */
     547         168 :         return (buf);
     548             : }
     549             : /* }}} */
     550             : 
     551             : /* {{{ php_do_ereg_replace
     552             :  */
     553         238 : static void php_do_ereg_replace(INTERNAL_FUNCTION_PARAMETERS, int icase)
     554             : {
     555             :         zval *arg_pattern,
     556             :                 *arg_replace;
     557             :         zend_string *pattern, *arg_string;
     558             :         zend_string *string;
     559             :         zend_string *replace;
     560             :         char *ret;
     561             :         
     562         238 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzS", &arg_pattern, &arg_replace, &arg_string) == FAILURE) {
     563          16 :                 return;
     564             :         }
     565             : 
     566         222 :         if (Z_TYPE_P(arg_pattern) == IS_STRING) {
     567         346 :                 if (Z_STRVAL_P(arg_pattern) && Z_STRLEN_P(arg_pattern)) {
     568         340 :                         pattern = zend_string_copy(Z_STR_P(arg_pattern));
     569             :                 } else {
     570           6 :                         pattern = STR_EMPTY_ALLOC();
     571             :                 }
     572             :         } else {
     573          66 :                 convert_to_long_ex(arg_pattern);
     574          46 :                 pattern = zend_string_alloc(1, 0);
     575          46 :                 pattern->val[0] = (char) Z_LVAL_P(arg_pattern);
     576          46 :                 pattern->val[1] = '\0';
     577             :         }
     578             : 
     579         222 :         if (Z_TYPE_P(arg_replace) == IS_STRING) {
     580         346 :                 if (Z_STRVAL_P(arg_replace) && Z_STRLEN_P(arg_replace)) {
     581         340 :                         replace = zend_string_copy(Z_STR_P(arg_replace));
     582             :                 } else {
     583           6 :                         replace = STR_EMPTY_ALLOC();
     584             :                 }
     585             :         } else {
     586          66 :                 convert_to_long_ex(arg_replace);
     587          46 :                 replace = zend_string_alloc(1, 0);
     588          46 :                 replace->val[0] = (char) Z_LVAL_P(arg_replace);
     589          46 :                 replace->val[1] = '\0';
     590             :         }
     591             : 
     592         222 :         if (arg_string) {
     593         444 :                 string = zend_string_copy(arg_string);
     594             :         } else {
     595           0 :                 string = STR_EMPTY_ALLOC();
     596             :         }
     597             : 
     598             :         /* do the actual work */
     599         222 :         ret = php_ereg_replace(pattern->val, replace->val, string->val, icase, 1 TSRMLS_CC);
     600         222 :         if (ret == (char *) -1) {
     601          54 :                 RETVAL_FALSE;
     602             :         } else {
     603         336 :                 RETVAL_STRING(ret);
     604         168 :                 efree(ret);
     605             :         }
     606             : 
     607             :         zend_string_release(string);
     608             :         zend_string_release(replace);
     609             :         zend_string_release(pattern);
     610             : }
     611             : /* }}} */
     612             : 
     613             : /* {{{ proto string ereg_replace(string pattern, string replacement, string string)
     614             :    Replace regular expression */
     615         127 : PHP_FUNCTION(ereg_replace)
     616             : {
     617         127 :         php_do_ereg_replace(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
     618         127 : }
     619             : /* }}} */
     620             : 
     621             : /* {{{ proto string eregi_replace(string pattern, string replacement, string string)
     622             :    Case insensitive replace regular expression */
     623         111 : PHP_FUNCTION(eregi_replace)
     624             : {
     625         111 :         php_do_ereg_replace(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     626         111 : }
     627             : /* }}} */
     628             : 
     629             : /* {{{ php_split
     630             :  */
     631         259 : static void php_split(INTERNAL_FUNCTION_PARAMETERS, int icase)
     632             : {
     633         259 :         zend_long count = -1;
     634             :         regex_t re;
     635             :         regmatch_t subs[1];
     636             :         char *spliton, *str, *strp, *endp;
     637             :         size_t spliton_len, str_len;
     638         259 :         int err, size, copts = 0;
     639             : 
     640         259 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &spliton, &spliton_len, &str, &str_len, &count) == FAILURE) {
     641          52 :                 return;
     642             :         }
     643             : 
     644         207 :         if (icase) {
     645         100 :                 copts = REG_ICASE;
     646             :         }
     647             : 
     648         207 :         strp = str;
     649         207 :         endp = strp + str_len;
     650             : 
     651         207 :         err = regcomp(&re, spliton, REG_EXTENDED | copts);
     652         207 :         if (err) {
     653          42 :                 php_ereg_eprint(err, &re TSRMLS_CC);
     654          42 :                 RETURN_FALSE;
     655             :         }
     656             : 
     657         165 :         array_init(return_value);
     658             : 
     659             :         /* churn through str, generating array entries as we go */
     660         515 :         while ((count == -1 || count > 1) && !(err = regexec(&re, strp, 1, subs, 0))) {
     661         295 :                 if (subs[0].rm_so == 0 && subs[0].rm_eo) {
     662             :                         /* match is at start of string, return empty string */
     663         102 :                         add_next_index_stringl(return_value, "", 0);
     664             :                         /* skip ahead the length of the regex match */
     665         102 :                         strp += subs[0].rm_eo;
     666          91 :                 } else if (subs[0].rm_so == 0 && subs[0].rm_eo == 0) {
     667             :                         /* No more matches */
     668             :                         regfree(&re);
     669             :                         
     670           8 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Regular Expression");
     671             :                         
     672           8 :                         zend_hash_destroy(Z_ARRVAL_P(return_value));
     673           8 :                         efree(Z_ARR_P(return_value));
     674           8 :                         RETURN_FALSE;
     675             :                 } else {
     676             :                         /* On a real match */
     677             : 
     678             :                         /* make a copy of the substring */
     679          83 :                         size = subs[0].rm_so;
     680             :                 
     681             :                         /* add it to the array */
     682          83 :                         add_next_index_stringl(return_value, strp, size);
     683             : 
     684             :                         /* point at our new starting point */
     685          83 :                         strp = strp + subs[0].rm_eo;
     686             :                 }
     687             : 
     688             :                 /* if we're only looking for a certain number of points,
     689             :                    stop looking once we hit it */
     690         185 :                 if (count != -1) {
     691          60 :                         count--;
     692             :                 }
     693             :         }
     694             : 
     695             :         /* see if we encountered an error */
     696         157 :         if (err && err != REG_NOMATCH) {
     697           0 :                 php_ereg_eprint(err, &re TSRMLS_CC);
     698             :                 regfree(&re);
     699           0 :                 zend_hash_destroy(Z_ARRVAL_P(return_value));
     700           0 :                 efree(Z_ARR_P(return_value));
     701           0 :                 RETURN_FALSE;
     702             :         }
     703             : 
     704             :         /* otherwise we just have one last element to add to the array */
     705         157 :         size = endp - strp;
     706             :         
     707         157 :         add_next_index_stringl(return_value, strp, size);
     708             : 
     709             :         regfree(&re);
     710             : }
     711             : /* }}} */
     712             : 
     713             : /* {{{ proto array split(string pattern, string string [, int limit])
     714             :    Split string into array by regular expression */
     715         133 : PHP_FUNCTION(split)
     716             : {
     717         133 :         php_split(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
     718         133 : }
     719             : /* }}} */
     720             : 
     721             : /* {{{ proto array spliti(string pattern, string string [, int limit])
     722             :    Split string into array by regular expression case-insensitive */
     723             : 
     724         126 : PHP_FUNCTION(spliti)
     725             : {
     726         126 :         php_split(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     727         126 : }
     728             : 
     729             : /* }}} */
     730             : 
     731             : /* {{{ proto string sql_regcase(string string)
     732             :    Make regular expression for case insensitive match */
     733          28 : PHP_EREG_API PHP_FUNCTION(sql_regcase)
     734             : {
     735             :         char *string, *tmp;
     736             :         size_t string_len;
     737             :         unsigned char c;
     738             :         register int i, j;
     739             : 
     740          28 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &string_len) == FAILURE) {
     741           8 :                 return;
     742             :         }
     743             :         
     744          20 :         tmp = safe_emalloc(string_len, 4, 1);
     745             :         
     746          83 :         for (i = j = 0; i < string_len; i++) {
     747          63 :                 c = (unsigned char) string[i];
     748          63 :                 if (isalpha(c)) {
     749          10 :                         tmp[j++] = '[';
     750          10 :                         tmp[j++] = toupper(c);
     751          10 :                         tmp[j++] = tolower(c);
     752          10 :                         tmp[j++] = ']';
     753             :                 } else {
     754          53 :                         tmp[j++] = c;
     755             :                 }
     756             :         }
     757          20 :         tmp[j] = 0;
     758             : 
     759          40 :         RETVAL_STRINGL(tmp, j);
     760          20 :         efree(tmp);
     761             : }
     762             : /* }}} */
     763             : 
     764             : /*
     765             :  * Local variables:
     766             :  * tab-width: 4
     767             :  * c-basic-offset: 4
     768             :  * End:
     769             :  * vim600: noet sw=4 ts=4 fdm=marker
     770             :  * vim<600: noet sw=4 ts=4
     771             :  */

Generated by: LCOV version 1.10

Generated at Fri, 19 Sep 2014 17:11:06 +0000 (2 days ago)

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