28 #include <freeradius-devel/util/debug.h>
31 #define SELECTOR_INDEX_UNSET INT32_MAX
109 char *q =
out, *end =
out + outlen;
111 if (outlen == 0)
return 0;
113 while (*p && (q < end)) {
115 if ((q + 1) >= end)
break;
148 bool child_matched =
false;
157 if (!json_object_is_type(
object, json_type_object))
return 0;
158 if (!json_object_object_get_ex(
object, node->
selector->field, &
object))
return 0;
166 for (selector = node->
selector; selector; selector = selector->
next)
switch (selector->
type) {
169 struct array_list *array_obj;
173 if (!json_object_is_type(
object, json_type_array))
return 0;
174 array_obj = json_object_get_array(
object);
175 if ((selector->slice[0] < 0) ||
176 (selector->slice[0] >= (int32_t)(array_obj->length & INT32_MAX)))
continue;
179 array_obj->array[selector->slice[0]], node->
next);
180 if (ret < 0)
return ret;
181 if (ret == 1) child_matched =
true;
187 struct array_list *array_obj;
188 int32_t start, end, step, i;
190 if (!json_object_is_type(
object, json_type_array))
return 0;
191 array_obj = json_object_get_array(
object);
197 step = selector->slice[2];
200 start = selector->slice[0];
202 (int32_t)((array_obj->length - 1) & INT32_MAX) : 0;
203 else if (start < 0) start = array_obj->length + start;
205 end = selector->slice[1];
207 -1 : (int32_t)((array_obj->length - 1) & INT32_MAX);
208 else if (end < 0) end = array_obj->length + end;
213 if (step < 0)
for (i = start; (i > end) && (i >= 0); i += step) {
214 fr_assert((i >= 0) && (i < (int32_t)(array_obj->length & INT32_MAX)));
216 array_obj->array[i], node->
next);
217 if (ret < 0)
return ret;
218 if (ret == 1) child_matched =
true;
222 }
else for (i = start; (i < end) && (i < (int32_t)(array_obj->length & INT32_MAX)); i += step) {
223 fr_assert((i >= 0) && (i < (int32_t)(array_obj->length & INT32_MAX)));
225 array_obj->array[i], node->
next);
226 if (ret < 0)
return ret;
227 if (ret == 1) child_matched =
true;
236 return child_matched ? 1 : 0;
245 if (json_object_is_type(
object, json_type_array)) {
246 struct array_list *array_obj;
248 array_obj = json_object_get_array(
object);
249 for (i = 0; i < (int32_t)(array_obj->length & INT32_MAX); i++) {
251 array_obj->array[i], node->
next);
252 if (ret < 0)
return ret;
253 if (ret == 1) child_matched =
true;
255 return child_matched ? 1 : 0;
256 }
else if (json_object_is_type(
object, json_type_object)) {
257 json_object_object_foreach(
object, field_name, field_value) {
264 field_value, node->
next);
265 if (ret < 0)
return ret;
266 if (ret == 1) child_matched =
true;
268 return child_matched ? 1 : 0;
279 if (json_object_is_type(
object, json_type_array)) {
280 struct array_list *array_obj;
285 array_obj = json_object_get_array(
object);
286 for (i = 0; i < (int32_t)(array_obj->length & INT32_MAX); i++) {
288 array_obj->array[i], node);
289 if (ret < 0)
return ret;
290 if (ret == 1) child_matched =
true;
298 if (ret < 0)
return ret;
299 if (ret == 1) child_matched =
true;
301 return child_matched ? 1 : 0;
302 }
else if (json_object_is_type(
object, json_type_object)) {
306 json_object_object_foreach(
object, field_name, field_value) {
314 if (ret < 0)
return ret;
315 if (ret == 1) child_matched =
true;
323 if (ret < 0)
return ret;
324 if (ret == 1) child_matched =
true;
326 return child_matched ? 1 : 0;
363 fr_value_box_list_insert_tail(tail,
value);
387 if (!root)
return -1;
417 p = talloc_zero_array(ctx,
char, 1);
421 p = talloc_strdup_append_buffer(p,
"$");
425 p = talloc_strdup_append_buffer(p,
"@");
429 p = talloc_strdup_append_buffer(p,
".*");
437 p = talloc_asprintf_append_buffer(p,
".%s",
buffer);
448 p = talloc_strdup_append_buffer(p,
"[");
449 for (selector = node->
selector; selector; selector = selector->
next)
switch (selector->
type) {
451 p = talloc_asprintf_append_buffer(p,
"%i%s", selector->slice[0], selector->
next ?
"," :
"");
456 p = talloc_strdup_append_buffer(p,
":");
458 p = talloc_asprintf_append_buffer(p,
"%i:", selector->slice[0]);
461 p = talloc_strdup_append_buffer(p,
":");
463 p = talloc_asprintf_append_buffer(p,
"%i", selector->slice[1]);
465 p = talloc_asprintf_append_buffer(p,
"%i:", selector->slice[1]);
468 p = talloc_asprintf_append_buffer(p,
"%i", selector->slice[2]);
470 if (selector->
next) p = talloc_strdup_append_buffer(p,
",");
477 p = talloc_strdup_append_buffer(p,
"]");
484 p = talloc_strdup_append_buffer(p,
"..");
488 p = talloc_strdup_append_buffer(p,
".");
548 char const *p, *end =
in +
inlen;
562 for (p =
in; p < end; p++)
if ((p[0] ==
',') || (p[0] ==
']'))
break;
590 num = (int32_t)strtol(p, &q, 10);
591 if (q > p)
switch (q[0]) {
598 selector->slice[idx] = num;
602 selector->slice[idx] = num;
605 if (q[0] !=
':')
goto no_term;
614 num = (int32_t)strtol(p, &q, 10);
615 if (q > p)
switch (q[0]) {
620 selector->slice[idx] = num;
624 selector->slice[idx] = num;
627 if (q[0] !=
':')
goto no_term;
634 num = (int32_t)strtol(p, &q, 10);
644 selector->slice[idx] = num;
656 char const *p =
in, *end = p +
inlen;
657 char *buff_p =
buffer, *buff_end = buff_p +
sizeof(
buffer);
665 if (buff_p == buff_end) {
681 if ((buff_p + clen) >= buff_end)
goto name_too_big;
682 memcpy(buff_p, p, clen);
697 if (++p == end)
return p -
in;
733 char const *p =
in, *end = p +
inlen;
769 if (p == end)
goto missing_terminator;
778 if (p[0] ==
']')
break;
781 "or selector terminator ']'");
784 if (++p == end)
goto missing_terminator;
794 stail = &selector->
next;
796 if (p[0] !=
']')
goto missing_terminator;
815 TALLOC_CTX *tail_ctx = ctx;
820 char const *p =
in, *end = p +
inlen;
824 #define NODE_NEW(_node) \
826 tail_ctx = *tail = (_node) = talloc_zero(tail_ctx, fr_jpath_node_t); \
827 (_node)->selector = talloc_zero((_node), jpath_selector_t); \
828 tail = &(_node)->next; \
873 "wildcard '*' or field specifier");
890 if ((p != end) && (p[1] ==
'.')) {
892 "followed by child delimiter '.'");
898 if ((p + 1) == end) {
910 if (p[1] ==
'[') p++;
928 if (p == end)
return p -
in;
940 if (p == end)
return p -
in;
static int const char char buffer[256]
char const * literal
Operand is a literal (value)
@ JPATH_OPERAND_JPATH
Operand is a jpath sequence.
@ JPATH_OPERAND_LITERAL
Operand is a literal.
jpath_operand_t rhs
RHS value.
fr_jpath_node_t * next
Next in the jpath chain.
jpath_operand_t lhs
LHS value.
char * fr_jpath_asprint(TALLOC_CTX *ctx, fr_jpath_node_t const *head)
Print a node list to a string for debugging.
static char const escape_chars[]
fr_jpath_node_t * jpath
Operand is a jpath expression.
#define SELECTOR_INDEX_UNSET
jpath_selector_t * selector
Jpath selector head (there may be multiple).
@ JPATH_SELECTOR_EXPRESSION
Expression (NYI).
@ JPATH_SELECTOR_CURRENT
Continue at the current node in the document.
@ JPATH_SELECTOR_INDEX
Array index, current JSON node must be an array.
@ JPATH_SELECTOR_SLICE
Array slice, current JSON node must be an array.
@ JPATH_SELECTOR_FIELD
A field, current JSON node must be an object.
@ JPATH_SELECTOR_RECURSIVE_DESCENT
Descend through the JSON tree, looking for a node which matches the next one in the jpath sequence.
@ JPATH_SELECTOR_ROOT
Jump to the root of the document.
@ JPATH_SELECTOR_FILTER_EXPRESSION
Complex filter expression (NYI).
@ JPATH_SELECTOR_WILDCARD
Wildcard, operate over all array indices, or fields.
int fr_jpath_evaluate_leaf(TALLOC_CTX *ctx, fr_value_box_list_t *out, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, json_object *root, fr_jpath_node_t const *jpath)
Evaluate a parsed jpath expression against a json-c tree.
static size_t jpath_field_parse(fr_jpath_node_t *node, char const *in, size_t inlen)
Parse a jpath field.
ssize_t fr_jpath_escape_func(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Escapes special chars.
static ssize_t jpath_filter_expr_parse(UNUSED jpath_selector_t *selector, UNUSED char const *in, UNUSED size_t inlen)
Parse a jpath filter expression, which in our case, is a FreeRADIUS condition.
jpath_type_t type
Type of the Jpath node.
static size_t jpath_selector_parse(fr_jpath_node_t *node, char const *in, size_t inlen)
parse a jpath selector
static ssize_t jpath_expr_parse(UNUSED jpath_selector_t *selector, UNUSED char const *in, UNUSED size_t inlen)
Parse a jpath expression.
static ssize_t jpath_array_parse(jpath_selector_t *selector, char const *in, size_t inlen)
Parse index/slice notation.
ssize_t fr_jpath_parse(TALLOC_CTX *ctx, fr_jpath_node_t **head, char const *in, size_t inlen)
Parse a jpath string.
static int jpath_evaluate(TALLOC_CTX *ctx, fr_value_box_list_t *tail, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, json_object *object, fr_jpath_node_t const *jpath)
Recursive function for jpath_expr_evaluate.
Node in a jpath selector sequence.
A jpath expression for performing complex comparisons against field values.
Operand in a jpath expression.
int fr_json_object_to_value_box(TALLOC_CTX *ctx, fr_value_box_t *out, json_object *object, fr_dict_attr_t const *enumv, bool tainted)
Convert json object to fr_value_box_t.
size_t fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
Master include file to access all functions and structures in the library.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
static size_t char fr_sbuff_t size_t inlen
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
static size_t char ** out