]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
v4: Convert %{Foreach} to new xlat API (#4091)
authorNick Porter <nick@portercomputing.co.uk>
Thu, 20 May 2021 17:45:00 +0000 (18:45 +0100)
committerGitHub <noreply@github.com>
Thu, 20 May 2021 17:45:00 +0000 (19:45 +0200)
* Convert %{Foreach...} to new xlat api

* Allow virtual attributes to use new xlat API

src/lib/unlang/foreach.c
src/lib/unlang/xlat_eval.c

index 886f9063dcdcdb1b5ca83e53ffd4935e2e834b1b..2bf555648627db4ad13b0b484c5896e1c063af4d 100644 (file)
@@ -29,6 +29,7 @@ RCSID("$Id$")
 #include "foreach_priv.h"
 #include "return_priv.h"
 #include "unlang_priv.h"
+#include "xlat_priv.h"
 
 static char const * const xlat_foreach_names[] = {"Foreach-Variable-0",
                                                  "Foreach-Variable-1",
@@ -59,9 +60,9 @@ typedef struct {
 #endif
 } unlang_frame_state_foreach_t;
 
-static ssize_t unlang_foreach_xlat(TALLOC_CTX *ctx, char **out, UNUSED size_t outlen,
-                                  void const *mod_inst, UNUSED void const *xlat_inst,
-                                  request_t *request, UNUSED char const *fmt);
+static xlat_action_t unlang_foreach_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request,
+                                        UNUSED void const *xlat_inst, void *xlat_thread_inst,
+                                        UNUSED fr_value_box_list_t *in);
 
 #define FOREACH_REQUEST_DATA (void *)unlang_foreach_xlat
 
@@ -196,16 +197,21 @@ static unlang_action_t unlang_break(rlm_rcode_t *p_result, request_t *request, u
  *
  * @ingroup xlat_functions
  */
-static ssize_t unlang_foreach_xlat(TALLOC_CTX *ctx, char **out, UNUSED size_t outlen,
-                                  void const *mod_inst, UNUSED void const *xlat_inst,
-                                  request_t *request, UNUSED char const *fmt)
+static xlat_action_t unlang_foreach_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request,
+                                        void const *xlat_inst, UNUSED void *xlat_thread_inst,
+                                        UNUSED fr_value_box_list_t *in)
 {
-       fr_pair_t       **pvp;
+       fr_pair_t                       **pvp;
+       int const                       *inst = xlat_inst;
+       fr_value_box_t                  *vb;
 
-       pvp = (fr_pair_t **) request_data_reference(request, FOREACH_REQUEST_DATA, *(int const *) mod_inst);
-       if (!pvp || !*pvp) return 0;
+       pvp = (fr_pair_t **) request_data_reference(request, FOREACH_REQUEST_DATA, *inst);
+       if (!pvp || !*pvp) return XLAT_ACTION_FAIL;
 
-       return fr_value_box_aprint(ctx, out, &(*pvp)->data, NULL);
+       MEM(vb = fr_value_box_alloc_null(ctx));
+       fr_value_box_copy(ctx, vb, &(*pvp)->data);
+       fr_dcursor_append(out, vb);
+       return XLAT_ACTION_DONE;
 }
 
 void unlang_foreach_init(void)
@@ -215,8 +221,9 @@ void unlang_foreach_init(void)
        for (i = 0; i < NUM_ELEMENTS(xlat_foreach_names); i++) {
                xlat_t *x;
 
-               x = xlat_register_legacy(&xlat_foreach_inst[i], xlat_foreach_names[i],
-                                        unlang_foreach_xlat, NULL, NULL, 0, 0);
+               x = xlat_register(NULL, xlat_foreach_names[i],
+                                 unlang_foreach_xlat, true);
+               x->uctx = &xlat_foreach_inst[i];
                fr_assert(x);
                xlat_internal(x);
        }
index 23fe8405967f0db0a3b1e9145eebae956f331a8a..284cdbd9914c1dc9a34971bcc5d76a8fe69f4046 100644 (file)
@@ -1311,17 +1311,21 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_exp_t con
                                   node->fmt);
 
                        xlat_debug_log_expansion(request, node, NULL);
-                       MEM(value = fr_value_box_alloc_null(ctx));
-                       slen = node->call.func->func.sync(value, &str, node->call.func->buf_len, node->call.func->mod_inst,
+                       if (node->call.func->type == XLAT_FUNC_NORMAL) {
+                               node->call.func->func.async(ctx, out, request, node->call.func->uctx, NULL, NULL);
+                       } else {
+                               MEM(value = fr_value_box_alloc_null(ctx));
+                               slen = node->call.func->func.sync(value, &str, node->call.func->buf_len, node->call.func->mod_inst,
                                                     NULL, request, NULL);
-                       if (slen < 0) {
-                               talloc_free(value);
-                               goto fail;
-                       }
-                       if (slen == 0) continue;
+                               if (slen < 0) {
+                                       talloc_free(value);
+                                       goto fail;
+                               }
+                               if (slen == 0) continue;
 
-                       fr_value_box_bstrdup_buffer_shallow(NULL, value, NULL, str, false);
-                       fr_dcursor_append(out, value);
+                               fr_value_box_bstrdup_buffer_shallow(NULL, value, NULL, str, false);
+                               fr_dcursor_append(out, value);
+                       }
                        fr_dcursor_next(out);
 
                        xlat_debug_log_result(request, fr_dcursor_current(out));
@@ -1507,6 +1511,37 @@ static char *xlat_sync_eval(TALLOC_CTX *ctx, request_t *request, xlat_exp_t cons
        case XLAT_VIRTUAL:
                XLAT_DEBUG("xlat_sync_eval VIRTUAL");
 
+               /*
+                *      Temporary hack to use the new API
+                */
+               if (node->call.func->type == XLAT_FUNC_NORMAL) {
+                       fr_value_box_list_t     result;
+                       xlat_action_t           action;
+                       fr_dcursor_t            out;
+                       TALLOC_CTX              *pool = talloc_new(NULL);
+
+                       fr_value_box_list_init (&result);
+                       fr_dcursor_init(&out, &result);
+
+                       action = node->call.func->func.async(pool, &out, request, node->call.func->uctx, NULL, NULL);
+                       if (action == XLAT_ACTION_FAIL) {
+                               talloc_free(pool);
+                               return NULL;
+                       }
+                       if (!fr_dlist_empty(&result)) {
+                               str = fr_value_box_list_aprint(ctx, &result, NULL, &fr_value_escape_double);
+                               if (!str) {
+                                       RPEDEBUG("Failed concatenating xlat result string");
+                                       talloc_free(pool);
+                                       return NULL;
+                               }
+                       } else {
+                               str = talloc_strdup(ctx, "");
+                       }
+                       talloc_free(pool);      /* Memory should be in new ctx */
+                       break;
+               }
+
                if (node->call.func->buf_len > 0) {
                        str = talloc_array(ctx, char, node->call.func->buf_len);
                        str[0] = '\0';  /* Be sure the string is \0 terminated */