php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #64730
Patch second_arg_rege_key.patch revision 2013-05-04 12:35 UTC by laruence@php.net
Patch sencode_argument.patch revision 2013-04-29 16:30 UTC by laruence@php.net

Patch second_arg_rege_key.patch for Regexps related Bug #64730

Patch version 2013-05-04 12:35 UTC

Return to Bug #64730 | Download this patch
Patch Revisions:

Developer: laruence@php.net

diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index 0c7280e..676c9d2 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -848,10 +848,10 @@ static int preg_get_backref(char **str, int *backref)
 
 /* {{{ preg_do_repl_func
  */
-static int preg_do_repl_func(zval *function, char *subject, int *offsets, char **subpat_names, int count, char **result TSRMLS_DC)
+static int preg_do_repl_func(zval *function, zval* regex_key, char *subject, int *offsets, char **subpat_names, int count, char **result TSRMLS_DC)
 {
 	zval		*retval_ptr;		/* Function return value */
-	zval	   **args[1];			/* Argument to pass to function */
+	zval	   **args[2];			/* Argument to pass to function */
 	zval		*subpats;			/* Captured subpatterns */ 
 	int			 result_len;		/* Return value length */
 	int			 i;
@@ -865,8 +865,16 @@ static int preg_do_repl_func(zval *function, char *subject, int *offsets, char *
 		add_next_index_stringl(subpats, &subject[offsets[i<<1]], offsets[(i<<1)+1] - offsets[i<<1], 1);
 	}
 	args[0] = &subpats;
+	if (!regex_key) {
+		zval *null_key;
+		MAKE_STD_ZVAL(null_key);
+		ZVAL_NULL(null_key);
+		args[1] = &null_key;
+	} else {
+		args[1] = &regex_key;
+	}
 
-	if (call_user_function_ex(EG(function_table), NULL, function, &retval_ptr, 1, args, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) {
+	if (call_user_function_ex(EG(function_table), NULL, function, &retval_ptr, 2, args, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) {
 		convert_to_string_ex(&retval_ptr);
 		*result = estrndup(Z_STRVAL_P(retval_ptr), Z_STRLEN_P(retval_ptr));
 		result_len = Z_STRLEN_P(retval_ptr);
@@ -880,6 +888,9 @@ static int preg_do_repl_func(zval *function, char *subject, int *offsets, char *
 	}
 
 	zval_ptr_dtor(&subpats);
+	if (!regex_key) {
+		zval_ptr_dtor(args[1]);
+	}
 
 	return result_len;
 }
@@ -980,6 +991,18 @@ PHPAPI char *php_pcre_replace(char *regex,   int regex_len,
 							  zval *replace_val, int is_callable_replace,
 							  int *result_len, int limit, int *replace_count TSRMLS_DC)
 {
+	return php_pcre_replace_ex(regex, regex_len, NULL, subject, subject_len,
+			replace_val, is_callable_replace, result_len, limit, replace_count TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ php_pcre_replace_ex
+ */
+PHPAPI char *php_pcre_replace_ex(char *regex,   int regex_len, zval *regex_key,
+							  char *subject, int subject_len,
+							  zval *replace_val, int is_callable_replace,
+							  int *result_len, int limit, int *replace_count TSRMLS_DC)
+{
 	pcre_cache_entry	*pce;			    /* Compiled regular expression */
 
 	/* Compile regex or get it from cache. */
@@ -987,14 +1010,25 @@ PHPAPI char *php_pcre_replace(char *regex,   int regex_len,
 		return NULL;
 	}
 
-	return php_pcre_replace_impl(pce, subject, subject_len, replace_val, 
-		is_callable_replace, result_len, limit, replace_count TSRMLS_CC);
+	return php_pcre_replace_impl_ex(pce, regex_key, subject, subject_len, replace_val, 
+			is_callable_replace, result_len, limit, replace_count TSRMLS_CC);
 }
 /* }}} */
 
-/* {{{ php_pcre_replace_impl() */
-PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *replace_val, 
-	int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC)
+/* {{{ php_pcre_replace_impl
+ */
+PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len,
+		zval *replace_val, int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC)
+{
+	return php_pcre_replace_impl_ex(pce, NULL, subject, subject_len, replace_val,
+			is_callable_replace, result_len, limit, replace_count TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ php_pcre_replace_impl_ex
+ */
+PHPAPI char *php_pcre_replace_impl_ex(pcre_cache_entry *pce, zval *regex_key, char *subject, int subject_len,
+		zval *replace_val, int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC)
 {
 	pcre_extra		*extra = pce->extra;/* Holds results of studying */
 	pcre_extra		 extra_data;		/* Used locally for exec options */
@@ -1111,7 +1145,7 @@ PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int sub
 				new_len += eval_result_len;
 			} else if (is_callable_replace) {
 				/* Use custom function to get replacement string and its length. */
-				eval_result_len = preg_do_repl_func(replace_val, subject, offsets, subpat_names, count, &eval_result TSRMLS_CC);
+				eval_result_len = preg_do_repl_func(replace_val, regex_key, subject, offsets, subpat_names, count, &eval_result TSRMLS_CC);
 				new_len += eval_result_len;
 			} else { /* do regular substitution */
 				walk = replace;
@@ -1253,6 +1287,7 @@ static char *php_replace_in_subject(zval *regex, zval *replace, zval **subject,
 	
 	/* If regex is an array */
 	if (Z_TYPE_P(regex) == IS_ARRAY) {
+		zval *regex_key;
 		/* Duplicate subject string for repeated replacement */
 		subject_value = estrndup(Z_STRVAL_PP(subject), Z_STRLEN_PP(subject));
 		subject_len = Z_STRLEN_PP(subject);
@@ -1282,12 +1317,28 @@ static char *php_replace_in_subject(zval *regex, zval *replace, zval **subject,
 					/* We've run out of replacement strings, so use an empty one */
 					replace_value = &empty_replace;
 				}
+			} else if (is_callable_replace) {
+				char *key;
+				ulong idx, key_len;
+				MAKE_STD_ZVAL(regex_key);
+				switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(regex), &key, &key_len, &idx, 0, NULL)) {
+					case HASH_KEY_IS_STRING:
+						ZVAL_STRINGL(regex_key, key, key_len, 1);
+						break;
+					case HASH_KEY_IS_LONG:
+						ZVAL_LONG(regex_key, idx);
+						break;
+					default:
+						ZVAL_NULL(regex_key);
+						break;
+				}
 			}
-			
+
 			/* Do the actual replacement and put the result back into subject_value
 			   for further replacements. */
-			if ((result = php_pcre_replace(Z_STRVAL_PP(regex_entry),
+			if ((result = php_pcre_replace_ex(Z_STRVAL_PP(regex_entry),
 										   Z_STRLEN_PP(regex_entry),
+										   regex_key,
 										   subject_value,
 										   subject_len,
 										   replace_value,
@@ -1299,10 +1350,17 @@ static char *php_replace_in_subject(zval *regex, zval *replace, zval **subject,
 				subject_value = result;
 				subject_len = *result_len;
 			} else {
+				if (is_callable_replace) {
+					zval_ptr_dtor(&regex_key);
+				}
 				efree(subject_value);
 				return NULL;
 			}
 
+			if (is_callable_replace) {
+				zval_ptr_dtor(&regex_key);
+			}
+
 			zend_hash_move_forward(Z_ARRVAL_P(regex));
 		}
 
diff --git a/ext/pcre/php_pcre.h b/ext/pcre/php_pcre.h
index d4acae0..9dd1cac 100644
--- a/ext/pcre/php_pcre.h
+++ b/ext/pcre/php_pcre.h
@@ -34,6 +34,7 @@
 #endif
 
 PHPAPI char *php_pcre_replace(char *regex, int regex_len, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC);
+PHPAPI char *php_pcre_replace_ex(char *regex, int regex_len, zval *regex_key, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC);
 PHPAPI pcre* pcre_get_compiled_regex(char *regex, pcre_extra **extra, int *options TSRMLS_DC);
 PHPAPI pcre* pcre_get_compiled_regex_ex(char *regex, pcre_extra **extra, int *preg_options, int *coptions TSRMLS_DC);
 
@@ -60,6 +61,9 @@ PHPAPI void  php_pcre_match_impl(  pcre_cache_entry *pce, char *subject, int sub
 PHPAPI char *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value, 
 	int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC);
 
+PHPAPI char *php_pcre_replace_impl_ex(pcre_cache_entry *pce, zval *regex_key, char *subject, int subject_len,
+		zval *return_value, int is_callable_replace, int *result_len, int limit, int *replace_count TSRMLS_DC);
+
 PHPAPI void  php_pcre_split_impl(  pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value,
 	long limit_val, long flags TSRMLS_DC);
 
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Apr 23 13:01:29 2024 UTC