On 11/27/2014 02:46 PM, jkal...@apache.org wrote: > Author: jkaluza > Date: Thu Nov 27 13:46:11 2014 > New Revision: 1642154 > > URL: http://svn.apache.org/r1642154 > Log: > * ap_exr: Add replace(string, from, to) function. > > Modified: > httpd/httpd/trunk/docs/manual/expr.xml > httpd/httpd/trunk/include/ap_expr.h > httpd/httpd/trunk/server/util_expr_eval.c > httpd/httpd/trunk/server/util_expr_parse.y >
> Modified: httpd/httpd/trunk/server/util_expr_eval.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_expr_eval.c?rev=1642154&r1=1642153&r2=1642154&view=diff > ============================================================================== > --- httpd/httpd/trunk/server/util_expr_eval.c (original) > +++ httpd/httpd/trunk/server/util_expr_eval.c Thu Nov 27 13:46:11 2014 > @@ -183,13 +186,29 @@ static const char *ap_expr_eval_string_f > const ap_expr_t *info, > const ap_expr_t *arg) > { > - ap_expr_string_func_t *func = (ap_expr_string_func_t *)info->node_arg1; > const void *data = info->node_arg2; > > AP_DEBUG_ASSERT(info->node_op == op_StringFuncInfo); > - AP_DEBUG_ASSERT(func != NULL); > + AP_DEBUG_ASSERT(info->node_arg1 != NULL); > AP_DEBUG_ASSERT(data != NULL); > - return (*func)(ctx, data, ap_expr_eval_word(ctx, arg)); > + if (arg->node_op == op_ListElement) { > + /* Evaluate the list elements and store them in apr_array_header. */ > + ap_expr_string_list_func_t *func = (ap_expr_string_list_func_t > *)info->node_arg1; > + apr_array_header_t *args = apr_array_make(ctx->p, 1, sizeof(char *)); Shouldn't we use at least 2 instead of 1? I guess we expect at least 2 elements. > + do { > + const ap_expr_t *val = arg->node_arg1; > + const char **new = apr_array_push(args); > + *new = ap_expr_eval_word(ctx, val); > + > + arg = arg->node_arg2; > + } while (arg != NULL); > + > + return (*func)(ctx, data, args); > + } > + else { > + ap_expr_string_func_t *func = (ap_expr_string_func_t > *)info->node_arg1; > + return (*func)(ctx, data, ap_expr_eval_word(ctx, arg)); > + } > } > > static int intstrcmp(const char *s1, const char *s2) > @@ -1071,6 +1110,59 @@ static const char *ldap_func(ap_expr_eva > } > #endif > > +static int replace_func_parse_arg(ap_expr_lookup_parms *parms) > +{ > + const char *original = parms->arg; > + const apr_strmatch_pattern *pattern; > + > + if (!parms->arg) { > + *parms->err = apr_psprintf(parms->ptemp, "replace() function needs " > + "exactly 3 arguments"); > + return !OK; > + } > + pattern = apr_strmatch_precompile(parms->pool, original, 0); > + *parms->data = pattern; > + return OK; > +} > + > +static const char *replace_func(ap_expr_eval_ctx_t *ctx, const void *data, > + const apr_array_header_t *args) > +{ > + char *buff, *original, *replacement; > + struct ap_varbuf vb; > + apr_size_t repl_len; > + const char *repl; > + apr_size_t bytes; > + apr_size_t len; > + const apr_strmatch_pattern *pattern = data; > + if (args->nelts != 3) { > + *ctx->err = apr_psprintf(ctx->p, "replace() function needs " > + "exactly 3 arguments"); > + return ""; > + } > + > + buff = APR_ARRAY_IDX(args, 2, char *); > + original = APR_ARRAY_IDX(args, 1, char *); > + replacement = APR_ARRAY_IDX(args, 0, char *); > + repl_len = strlen(replacement); > + bytes = strlen(buff); > + > + ap_varbuf_init(ctx->p, &vb, 0); > + vb.strlen = 0; > + > + while ((repl = apr_strmatch(pattern, buff, bytes))) { > + len = (apr_size_t) (repl - buff); > + ap_varbuf_strmemcat(&vb, buff, len); > + ap_varbuf_strmemcat(&vb, replacement, repl_len); > + > + len += repl_len; This goes wrong if replacement string and original string are of different size. IMHO you need to add strlen(original) to len above. > + bytes -= len; > + buff += len; > + } > + > + return ap_varbuf_pdup(ctx->p, &vb, NULL, 0, buff, bytes, &len); > +} > + > #define MAX_FILE_SIZE 10*1024*1024 > static const char *file_func(ap_expr_eval_ctx_t *ctx, const void *data, > char *arg) > @@ -1657,6 +1749,7 @@ static const struct expr_provider_single Regards Rüdiger