|
|
|
@ -986,88 +986,6 @@ static zend_string *preg_do_repl_func(zval *function, char *subject, int *offset |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ preg_do_eval |
|
|
|
*/ |
|
|
|
static zend_string *preg_do_eval(char *eval_str, int eval_str_len, char *subject, |
|
|
|
int *offsets, int count) |
|
|
|
{ |
|
|
|
zval retval; /* Return value from evaluation */ |
|
|
|
char *eval_str_end, /* End of eval string */ |
|
|
|
*match, /* Current match for a backref */ |
|
|
|
*walk, /* Used to walk the code string */ |
|
|
|
*segment, /* Start of segment to append while walking */ |
|
|
|
walk_last; /* Last walked character */ |
|
|
|
int match_len; /* Length of the match */ |
|
|
|
int backref; /* Current backref */ |
|
|
|
zend_string *esc_match; /* Quote-escaped match */ |
|
|
|
zend_string *result_str; |
|
|
|
char *compiled_string_description; |
|
|
|
smart_str code = {0}; |
|
|
|
|
|
|
|
eval_str_end = eval_str + eval_str_len; |
|
|
|
walk = segment = eval_str; |
|
|
|
walk_last = 0; |
|
|
|
|
|
|
|
while (walk < eval_str_end) { |
|
|
|
/* If found a backreference.. */ |
|
|
|
if ('\\' == *walk || '$' == *walk) { |
|
|
|
smart_str_appendl(&code, segment, walk - segment); |
|
|
|
if (walk_last == '\\') { |
|
|
|
code.s->val[code.s->len-1] = *walk++; |
|
|
|
segment = walk; |
|
|
|
walk_last = 0; |
|
|
|
continue; |
|
|
|
} |
|
|
|
segment = walk; |
|
|
|
if (preg_get_backref(&walk, &backref)) { |
|
|
|
if (backref < count) { |
|
|
|
/* Find the corresponding string match and substitute it |
|
|
|
in instead of the backref */ |
|
|
|
match = subject + offsets[backref<<1]; |
|
|
|
match_len = offsets[(backref<<1)+1] - offsets[backref<<1]; |
|
|
|
if (match_len) { |
|
|
|
esc_match = php_addslashes(zend_string_init(match, match_len, 0), 1); |
|
|
|
} else { |
|
|
|
esc_match = zend_string_init(match, match_len, 0); |
|
|
|
} |
|
|
|
} else { |
|
|
|
esc_match = STR_EMPTY_ALLOC(); |
|
|
|
} |
|
|
|
smart_str_appendl(&code, esc_match->val, esc_match->len); |
|
|
|
|
|
|
|
segment = walk; |
|
|
|
|
|
|
|
/* Clean up and reassign */ |
|
|
|
zend_string_release(esc_match); |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
walk++; |
|
|
|
walk_last = walk[-1]; |
|
|
|
} |
|
|
|
smart_str_appendl(&code, segment, walk - segment); |
|
|
|
smart_str_0(&code); |
|
|
|
|
|
|
|
compiled_string_description = zend_make_compiled_string_description("regexp code"); |
|
|
|
/* Run the code */ |
|
|
|
if (zend_eval_stringl(code.s->val, code.s->len, &retval, compiled_string_description) == FAILURE) { |
|
|
|
efree(compiled_string_description); |
|
|
|
php_error_docref(NULL,E_ERROR, "Failed evaluating code: %s%s", PHP_EOL, code.s->val); |
|
|
|
/* zend_error() does not return in this case */ |
|
|
|
} |
|
|
|
efree(compiled_string_description); |
|
|
|
|
|
|
|
/* Save the return string */ |
|
|
|
result_str = zval_get_string(&retval); |
|
|
|
|
|
|
|
/* Clean up */ |
|
|
|
zval_dtor(&retval); |
|
|
|
smart_str_free(&code); |
|
|
|
|
|
|
|
return result_str; |
|
|
|
} |
|
|
|
/* }}} */ |
|
|
|
|
|
|
|
/* {{{ php_pcre_replace |
|
|
|
*/ |
|
|
|
PHPAPI zend_string *php_pcre_replace(zend_string *regex, |
|
|
|
@ -1103,7 +1021,6 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, |
|
|
|
int alloc_len; /* Actual allocated length */ |
|
|
|
int match_len; /* Length of the current match */ |
|
|
|
int backref; /* Backreference number */ |
|
|
|
int eval; /* If the replacement string should be eval'ed */ |
|
|
|
int start_offset; /* Where the new search starts */ |
|
|
|
int g_notempty=0; /* If the match should not be empty */ |
|
|
|
int replace_len=0; /* Length of replacement string */ |
|
|
|
@ -1117,7 +1034,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, |
|
|
|
int result_len; /* Length of result */ |
|
|
|
unsigned char *mark = NULL; /* Target for MARK name */ |
|
|
|
zend_string *result; /* Result of replacement */ |
|
|
|
zend_string *eval_result=NULL; /* Result of eval or custom function */ |
|
|
|
zend_string *eval_result=NULL; /* Result of custom function */ |
|
|
|
ALLOCA_FLAG(use_heap); |
|
|
|
|
|
|
|
if (extra == NULL) { |
|
|
|
@ -1127,22 +1044,16 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, |
|
|
|
extra->match_limit = (unsigned long)PCRE_G(backtrack_limit); |
|
|
|
extra->match_limit_recursion = (unsigned long)PCRE_G(recursion_limit); |
|
|
|
|
|
|
|
eval = pce->preg_options & PREG_REPLACE_EVAL; |
|
|
|
if (is_callable_replace) { |
|
|
|
if (eval) { |
|
|
|
php_error_docref(NULL, E_WARNING, "Modifier /e cannot be used with replacement callback"); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (pce->preg_options & PREG_REPLACE_EVAL) { |
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The /e modifier is no longer supported, use preg_replace_callback instead"); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
if (!is_callable_replace) { |
|
|
|
replace = Z_STRVAL_P(replace_val); |
|
|
|
replace_len = (int)Z_STRLEN_P(replace_val); |
|
|
|
replace_end = replace + replace_len; |
|
|
|
} |
|
|
|
|
|
|
|
if (eval) { |
|
|
|
php_error_docref(NULL, E_DEPRECATED, "The /e modifier is deprecated, use preg_replace_callback instead"); |
|
|
|
} |
|
|
|
|
|
|
|
/* Calculate the size of the offsets array, and allocate memory for it. */ |
|
|
|
num_subpats = pce->capture_count + 1; |
|
|
|
size_offsets = num_subpats * 3; |
|
|
|
@ -1201,13 +1112,8 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, |
|
|
|
match = subject + offsets[0]; |
|
|
|
|
|
|
|
new_len = result_len + offsets[0] - start_offset; /* part before the match */ |
|
|
|
|
|
|
|
/* If evaluating, do it and add the return string's length */ |
|
|
|
if (eval) { |
|
|
|
eval_result = preg_do_eval(replace, replace_len, subject, |
|
|
|
offsets, count); |
|
|
|
new_len += (int)eval_result->len; |
|
|
|
} else if (is_callable_replace) { |
|
|
|
|
|
|
|
if (is_callable_replace) { |
|
|
|
/* Use custom function to get replacement string and its length. */ |
|
|
|
eval_result = preg_do_repl_func(replace_val, subject, offsets, subpat_names, count, mark); |
|
|
|
new_len += (int)eval_result->len; |
|
|
|
@ -1243,10 +1149,9 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, |
|
|
|
|
|
|
|
/* copy replacement and backrefs */ |
|
|
|
walkbuf = result->val + result_len; |
|
|
|
|
|
|
|
/* If evaluating or using custom function, copy result to the buffer |
|
|
|
* and clean up. */ |
|
|
|
if (eval || is_callable_replace) { |
|
|
|
|
|
|
|
/* If using custom function, copy result to the buffer and clean up. */ |
|
|
|
if (is_callable_replace) { |
|
|
|
memcpy(walkbuf, eval_result->val, eval_result->len); |
|
|
|
result_len += (int)eval_result->len; |
|
|
|
if (eval_result) zend_string_release(eval_result); |
|
|
|
|