28 #include <freeradius-devel/rad_assert.h>
31 #define SELECTOR_INDEX_UNSET INT32_MAX
113 char *q = out, *end = out + outlen;
115 if (outlen == 0)
return 0;
117 while (*p && (q < end)) {
119 if ((q + 1) >= end)
break;
152 bool child_matched =
false;
170 for (selector = node->
selector; selector; selector = selector->
next)
switch (selector->
type) {
173 struct array_list *array_obj;
178 array_obj = json_object_get_array(
object);
179 if (selector->slice[0] >= array_obj->length)
continue;
182 array_obj->array[selector->slice[0]], node->
next);
183 if (ret < 0)
return ret;
184 if (ret == 1) child_matched =
true;
190 struct array_list *array_obj;
191 int32_t start, end, step, i;
194 array_obj = json_object_get_array(
object);
200 step = selector->slice[2];
203 start = selector->slice[0];
205 else if (start < 0) start = array_obj->length + start;
207 end = selector->slice[1];
209 else if (end < 0) end = array_obj->length + end;
214 if (step < 0)
for (i = start; (i > end) && (i >= 0); i += step) {
217 array_obj->array[i], node->
next);
218 if (ret < 0)
return ret;
219 if (ret == 1) child_matched =
true;
223 }
else for (i = start; (i < end) && (i < array_obj->
length); i += step) {
224 rad_assert((i >= 0) && (i < array_obj->length));
226 array_obj->array[i], node->
next);
227 if (ret < 0)
return ret;
228 if (ret == 1) child_matched =
true;
237 return child_matched ? 1 : 0;
247 struct array_list *array_obj;
249 array_obj = json_object_get_array(
object);
250 for (i = 0; i < array_obj->length; i++) {
252 array_obj->array[i], node->
next);
253 if (ret < 0)
return ret;
254 if (ret == 1) child_matched =
true;
256 return child_matched ? 1 : 0;
265 field_value, node->
next);
266 if (ret < 0)
return ret;
267 if (ret == 1) child_matched =
true;
269 return child_matched ? 1 : 0;
281 struct array_list *array_obj;
286 array_obj = json_object_get_array(
object);
287 for (i = 0; i < array_obj->length; i++) {
289 array_obj->array[i], node);
290 if (ret < 0)
return ret;
291 if (ret == 1) child_matched =
true;
299 if (ret < 0)
return ret;
300 if (ret == 1) child_matched =
true;
302 return child_matched ? 1 : 0;
315 if (ret < 0)
return ret;
316 if (ret == 1) child_matched =
true;
324 if (ret < 0)
return ret;
325 if (ret == 1) child_matched =
true;
327 return child_matched ? 1 : 0;
359 *tail = &(**tail)->
next;
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,
".");
552 char const *p, *end = in + inlen;
566 for (p = in; p < end; p++)
if ((p[0] ==
',') || (p[0] ==
']'))
break;
578 if (inlen >
sizeof(buffer)) {
587 memcpy(&buffer, in, p - in);
588 buffer[p - in] =
'\0';
594 num = (int32_t)strtol(p, &q, 10);
595 if (q > p)
switch (q[0]) {
602 selector->slice[idx] = num;
606 selector->slice[idx] = num;
609 if (q[0] !=
':')
goto no_term;
618 num = (int32_t)strtol(p, &q, 10);
619 if (q > p)
switch (q[0]) {
624 selector->slice[idx] = num;
628 selector->slice[idx] = num;
631 if (q[0] !=
':')
goto no_term;
638 num = (int32_t)strtol(p, &q, 10);
648 selector->slice[idx] = num;
660 char const *p = in, *end = p + inlen;
661 char *buff_p = buffer, *buff_end = buff_p +
sizeof(buffer);
669 if (buff_p == buff_end) {
685 if ((buff_p + clen) >= buff_end)
goto name_too_big;
686 memcpy(buff_p, p, clen);
701 if (++p == end)
return p - in;
721 if (buff_p == buffer) {
737 char const *p = in, *end = p + inlen;
773 if (p == end)
goto missing_terminator;
782 if (p[0] ==
']')
break;
785 "or selector terminator ']'");
788 if (++p == end)
goto missing_terminator;
798 stail = &selector->
next;
800 if (p[0] !=
']')
goto missing_terminator;
819 TALLOC_CTX *tail_ctx = ctx;
824 char const *p = in, *end = p + inlen;
828 #define NODE_NEW(_node) \
830 tail_ctx = *tail = (_node) = talloc_zero(tail_ctx, fr_jpath_node_t); \
831 (_node)->selector = talloc_zero((_node), jpath_selector_t); \
832 tail = &(_node)->next; \
877 "wildcard '*' or field specifier");
894 if ((p != end) && (p[1] ==
'.')) {
896 "followed by child delimiter '.'");
902 if ((p + 1) == end) {
914 if (p[1] ==
'[') p++;
932 if (p == end)
return p - in;
944 if (p == end)
return p - in;
Complex filter expression (NYI).
int fr_jpath_evaluate_leaf(TALLOC_CTX *ctx, value_data_t **out, PW_TYPE 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.
#define json_object_object_foreach(obj, key, val)
int fr_json_object_to_value_data(TALLOC_CTX *ctx, value_data_t *out, json_object *object, PW_TYPE dst_type, fr_dict_attr_t const *dst_enumv)
Convert json object to value_data_t.
static size_t jpath_field_parse(fr_jpath_node_t *node, char const *in, size_t inlen)
Parse a jpath field.
jpath_operand_t rhs
RHS value.
Wildcard, operate over all array indicies, or fields.
Array index, current JSON node must be an array.
ssize_t fr_jpath_parse(TALLOC_CTX *ctx, fr_jpath_node_t **head, char const *in, size_t inlen)
Parse a jpath string.
static ssize_t jpath_array_parse(jpath_selector_t *selector, char const *in, size_t inlen)
Parse index/slice notation.
A jpath expression for performing complex comparisons against field values.
jpath_type_t type
Type of the Jpath node.
jpath_operand_type lhs_type
LHS type.
Array slice, current JSON node must be an array.
FR_TOKEN op
Comparison operator.
Jump to the root of the document.
int json_object_object_get_ex(struct json_object *jso, const char *key, struct json_object **value)
static ssize_t jpath_expr_parse(jpath_selector_t *selector, UNUSED char const *in, UNUSED size_t inlen)
Parse a jpath expression.
char const * literal
Operand is a literal (value)
static char const escape_chars[]
Descend through the JSON tree, looking for a node which matches the next one in the jpath sequence...
value_data_t * next
Next in a series of value_data.
fr_jpath_node_t * next
Next in the jpath chain.
#define SELECTOR_INDEX_UNSET
fr_jpath_node_t * jpath
Operand is a jpath expression.
Operand in a jpath expression.
char * fr_jpath_asprint(TALLOC_CTX *ctx, fr_jpath_node_t const *head)
Print a node list to a string for debugging.
Node in a jpath selector sequence.
Operand is a jpath sequence.
char * talloc_bstrndup(void const *t, char const *in, size_t inlen)
Binary safe strndup function.
static size_t jpath_selector_parse(fr_jpath_node_t *node, char const *in, size_t inlen)
parse a jpath selector
Continue at the current node in the document.
jpath_selector_t * selector
Jpath selector head (there may be multiple).
size_t fr_jpath_escape_func(UNUSED REQUEST *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Escapes special chars.
static int jpath_evaluate(TALLOC_CTX *ctx, value_data_t ***tail, PW_TYPE dst_type, fr_dict_attr_t const *dst_enumv, json_object *object, fr_jpath_node_t const *jpath)
Recursive function for jpath_expr_evaluate.
void fr_strerror_printf(char const *,...) CC_HINT(format(printf
jpath_operand_t lhs
LHS value.
static ssize_t jpath_filter_expr_parse(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.
struct jpath_expr jpath_expr_t
A jpath expression for performing complex comparisons against field values.
jpath_operand_type rhs_type
RHS type.
int 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.
#define fr_json_object_is_type(_obj, _type)
PW_TYPE
Internal data types used within libfreeradius.
A field, current JSON node must be an object.