Thanks for reviewing that commit. I've fixed both issues in r1643094.

Regards,
Jan Kaluza

On 12/02/2014 09:55 PM, Ruediger Pluem wrote:


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


Reply via email to