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: 266 306 86.9 %
Date: 2014-07-27 Functions: 19 21 90.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 27 Jul 2014 12:58:27 +0000 (37 hours ago)

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