Browse code

Merge aea932ba841416091b5ec93ef23011cd4257da68 into 432c7dd30976d1e4be9db35de39d67cc0e1a5e95

Alex Hermann authored on 23/10/2020 07:36:53 • GitHub committed on 23/10/2020 07:36:53
Showing 6 changed files
... ...
@@ -206,6 +206,44 @@ while($var(count) < $var(appendme_size)) {
206 206
     jansson_append('int', "", $var(tmp), "$var(appendme)");
207 207
     $var(count) = $var(count) + 1;
208 208
 }
209
+...
210
+        </programlisting>
211
+        </example>
212
+    </section>
213
+    <section id="jansson.f.jansson_xdecode">
214
+        <title>
215
+            <function moreinfo="none">jansson_xdecode(json, xavp)</function>
216
+        </title>
217
+        <para>
218
+            Parse a JSON string in 'json' and store the elements in xapv 'xavp'.
219
+            Top-level JSON must be an object or an array of objects.
220
+            Nested arrays and objects are not decoded but stored as string.
221
+        </para>
222
+        <example>
223
+        <title><function>jansson_xdecode</function> usage</title>
224
+        <programlisting format="linespecific">
225
+...
226
+jansson_xdecode('{"foo":"bar"}', "js");
227
+xlog("foo is $xavp(js=>foo)");
228
+...
229
+        </programlisting>
230
+        </example>
231
+    </section>
232
+    <section id="jansson.f.jansson_xencode">
233
+        <title>
234
+            <function moreinfo="none">jansson_xencode(xavp, pv)</function>
235
+        </title>
236
+        <para>
237
+            Encode the items in the xavp 'xavp' as JSON and store the result in a pv.
238
+            Nested xavps's are not supported.
239
+        </para>
240
+        <example>
241
+        <title><function>jansson_xencode</function> usage</title>
242
+        <programlisting format="linespecific">
243
+...
244
+$xavp(a=>foo) = "bar";
245
+jansson_xencode("a", "$var(js)");
246
+# $var(js) = '{"foo":"bar"}'
209 247
 ...
210 248
         </programlisting>
211 249
         </example>
... ...
@@ -27,6 +27,7 @@
27 27
 #include "../../core/mod_fix.h"
28 28
 #include "../../core/lvalue.h"
29 29
 #include "../../core/str.h"
30
+#include "../../core/xavp.h"
30 31
 
31 32
 #include "jansson_path.h"
32 33
 #include "jansson_funcs.h"
... ...
@@ -297,3 +298,193 @@ fail:
297 298
 	json_decref(json);
298 299
 	return -1;
299 300
 }
301
+
302
+
303
+static int jansson_object2xavp(json_t* obj, str *xavp)
304
+{
305
+	const char *key;
306
+	json_t *value;
307
+	sr_xavp_t *row = NULL;
308
+	sr_xval_t val;
309
+
310
+	json_object_foreach(obj, key, value) {
311
+		str name;
312
+		char* freeme = NULL;
313
+
314
+		if(jansson_to_xval(&val, &freeme, value)<0) {
315
+			ERR("failed to convert json object member value to xavp for key: %s\n", key);
316
+			if(freeme!=NULL) {
317
+				free(freeme);
318
+			}
319
+			return -1;
320
+		}
321
+
322
+		name.s = (char*)key;
323
+		name.len = strlen(name.s);
324
+
325
+		xavp_add_value(&name, &val, &row);
326
+
327
+		if(freeme!=NULL) {
328
+			free(freeme);
329
+		}
330
+	}
331
+
332
+	/* Add row to result xavp */
333
+	val.type = SR_XTYPE_XAVP;
334
+	val.v.xavp = row;
335
+	LM_DBG("Adding row\n");
336
+	xavp_add_value(xavp, &val, NULL);
337
+	return 1;
338
+}
339
+
340
+
341
+int jansson_xdecode(struct sip_msg* msg, char* src_in, char* xavp_in) {
342
+	str src_s;
343
+	str xavp_s;
344
+	json_t* json = NULL;
345
+	json_error_t parsing_error;
346
+
347
+	if (fixup_get_svalue(msg, (gparam_p)src_in, &src_s) != 0) {
348
+		ERR("cannot get json string value\n");
349
+		return -1;
350
+	}
351
+
352
+	if (fixup_get_svalue(msg, (gparam_p)xavp_in, &xavp_s) != 0) {
353
+		ERR("cannot get xavp string value\n");
354
+		return -1;
355
+	}
356
+
357
+	LM_DBG("decoding '%.*s' into '%.*s'\n", src_s.len, src_s.s, xavp_s.len, xavp_s.s);
358
+	json = json_loads(src_s.s, JSON_REJECT_DUPLICATES, &parsing_error);
359
+
360
+	if(!json) {
361
+		ERR("failed to parse json: %.*s\n", src_s.len, src_s.s);
362
+		ERR("json error at line %d, col %d: %s\n",
363
+				parsing_error.line, parsing_error.column, parsing_error.text);
364
+		return -1;
365
+	}
366
+
367
+	if (json_is_object(json)) {
368
+		if (jansson_object2xavp(json, &xavp_s) < 0) {
369
+			goto fail;
370
+		}
371
+	} else if (json_is_array(json)) {
372
+		size_t i;
373
+		json_t *value;
374
+
375
+		json_array_foreach(json, i, value) {
376
+			if (jansson_object2xavp(value, &xavp_s) < 0) {
377
+				goto fail;
378
+			}
379
+		}
380
+	} else {
381
+		LM_ERR("json root is not an object or array\n");
382
+		goto fail;
383
+	}
384
+
385
+	json_decref(json);
386
+	return 1;
387
+fail:
388
+	json_decref(json);
389
+	return -1;
390
+}
391
+
392
+static int jansson_xavp2object(json_t *json, sr_xavp_t **head) {
393
+	sr_xavp_t *avp = NULL;
394
+	json_t *it = NULL;
395
+
396
+	if(json==NULL)
397
+		return -1;
398
+
399
+	avp = *head;
400
+	if (avp->val.type != SR_XTYPE_XAVP) {
401
+		LM_ERR("cannot iterate xavp members\n");
402
+		return -1;
403
+	}
404
+	avp = avp->val.v.xavp;
405
+	while(avp)
406
+	{
407
+		switch(avp->val.type) {
408
+			case SR_XTYPE_NULL:
409
+				it = json_null();
410
+				break;
411
+			case SR_XTYPE_INT:
412
+				it = json_integer(avp->val.v.i);
413
+				break;
414
+			case SR_XTYPE_STR:
415
+				it = json_stringn(avp->val.v.s.s, avp->val.v.s.len);
416
+				break;
417
+			case SR_XTYPE_TIME:
418
+				it = json_integer((json_int_t)avp->val.v.t);
419
+				break;
420
+			case SR_XTYPE_LONG:
421
+				it = json_integer((json_int_t)avp->val.v.l);
422
+				break;
423
+			case SR_XTYPE_LLONG:
424
+				it = json_integer((json_int_t)avp->val.v.ll);
425
+				break;
426
+			case SR_XTYPE_XAVP:
427
+				it = json_string("<<xavp>>");
428
+				break;
429
+			case SR_XTYPE_DATA:
430
+				it = json_string("<<data>>");
431
+				break;
432
+			default:
433
+				LM_ERR("unknown xavp type: %d\n", avp->val.type);
434
+				return -1;
435
+		}
436
+		if (it == NULL) {
437
+			LM_ERR("failed to create json value\n");
438
+			return -1;
439
+		}
440
+		if (json_object_set_new(json, avp->name.s, it) < 0) {
441
+			LM_ERR("failed to add member to object\n");
442
+			return -1;
443
+		}
444
+		avp = avp->next;
445
+	}
446
+	return 1;
447
+}
448
+
449
+int jansson_xencode(struct sip_msg* msg, char* xavp, char* dst) {
450
+	str xavp_s;
451
+	json_t *json;
452
+	pv_spec_t *dst_pv;
453
+	pv_value_t dst_val;
454
+	sr_xavp_t *avp = NULL;
455
+	int ret = 1;
456
+
457
+	if (fixup_get_svalue(msg, (gparam_p)xavp, &xavp_s) != 0) {
458
+		LM_ERR("cannot get field string value\n");
459
+		return -1;
460
+	}
461
+
462
+	LM_DBG("encoding '%.*s' into '%p'\n", xavp_s.len, xavp_s.s, dst);
463
+
464
+	avp = xavp_get(&xavp_s, NULL);
465
+	if(avp==NULL || avp->val.type!=SR_XTYPE_XAVP) {
466
+		return -1;
467
+	}
468
+
469
+	json = json_object();
470
+	if (json == NULL) {
471
+		LM_ERR("could not obtain json handle\n");
472
+		return -1;
473
+	}
474
+	ret = jansson_xavp2object(json, &avp);
475
+	if (ret > 0) {
476
+		dst_val.rs.s = json_dumps(json, 0);
477
+		dst_val.rs.len = strlen(dst_val.rs.s);
478
+		dst_val.flags = PV_VAL_STR;
479
+		dst_pv = (pv_spec_t *)dst;
480
+		if (dst_pv->setf(msg, &dst_pv->pvp, (int)EQ_T, &dst_val) < 0) {
481
+			ret = -1;
482
+		}
483
+		free(dst_val.rs.s);
484
+	} else {
485
+		LM_ERR("json encoding failed\n");
486
+	}
487
+
488
+	json_decref(json);
489
+	return ret;
490
+}
... ...
@@ -33,5 +33,7 @@ int janssonmod_array_size(struct sip_msg* msg, char* json_in,
33 33
 		char* path_in, char* dst);
34 34
 int janssonmod_get_helper(sip_msg_t* msg, str *path_s, str *src_s,
35 35
 		pv_spec_t *dst_pv);
36
+int jansson_xdecode(struct sip_msg* msg, char* src_in, char* xavp_in);
37
+int jansson_xencode(struct sip_msg* msg, char* xavp, char* dst);
36 38
 
37 39
 #endif
... ...
@@ -38,6 +38,8 @@ static int fixup_get_params(void** param, int param_no);
38 38
 static int fixup_get_params_free(void** param, int param_no);
39 39
 static int fixup_set_params(void** param, int param_no);
40 40
 static int fixup_set_params_free(void** param, int param_no);
41
+static int fixup_xencode(void** param, int param_no);
42
+static int fixup_xencode_free(void** param, int param_no);
41 43
 
42 44
 
43 45
 int janssonmod_set_replace(struct sip_msg* msg, char* type_in, char* path_in,
... ...
@@ -64,11 +66,16 @@ static cmd_export_t cmds[]={
64 66
 		fixup_set_params, fixup_set_params_free, ANY_ROUTE},
65 67
 	{"jansson_append", (cmd_function)janssonmod_set_append, 4,
66 68
 		fixup_set_params, fixup_set_params_free, ANY_ROUTE},
69
+	{"jansson_xdecode", (cmd_function)jansson_xdecode, 2,
70
+		fixup_spve_spve, fixup_free_spve_spve, ANY_ROUTE},
71
+	{"jansson_xencode", (cmd_function)jansson_xencode, 2,
72
+		fixup_xencode, fixup_xencode_free, ANY_ROUTE},
67 73
 	/* for backwards compatibility */
68 74
 	{"jansson_get_field", (cmd_function)janssonmod_get_field, 3,
69 75
 		fixup_get_params, fixup_get_params_free, ANY_ROUTE},
70 76
 	/* non-script functions */
71 77
 	{"jansson_to_val", (cmd_function)jansson_to_val, 0, 0, 0, 0},
78
+
72 79
 	{0, 0, 0, 0, 0, 0}
73 80
 };
74 81
 
... ...
@@ -142,6 +149,43 @@ static int fixup_set_params_free(void** param, int param_no)
142 149
 	return -1;
143 150
 }
144 151
 
152
+static int fixup_xencode(void** param, int param_no)
153
+{
154
+	if (param_no == 1) {
155
+		return fixup_spve_null(param, 1);
156
+	}
157
+
158
+	if (param_no == 2) {
159
+		if (fixup_pvar_null(param, 1) != 0) {
160
+		    LM_ERR("failed to fixup result pvar\n");
161
+		    return -1;
162
+		}
163
+		if (((pv_spec_t *)(*param))->setf == NULL) {
164
+		    LM_ERR("result pvar is not writeble\n");
165
+		    return -1;
166
+		}
167
+		return 0;
168
+	}
169
+
170
+	LM_ERR("invalid parameter number <%d>\n", param_no);
171
+	return -1;
172
+}
173
+
174
+static int fixup_xencode_free(void** param, int param_no)
175
+{
176
+	if (param_no == 1) {
177
+		fixup_free_spve_null(param, 1);
178
+		return 0;
179
+	}
180
+
181
+	if (param_no == 2) {
182
+		return fixup_free_pvar_null(param, 1);
183
+	}
184
+
185
+	LM_ERR("invalid parameter number <%d>\n", param_no);
186
+	return -1;
187
+}
188
+
145 189
 /* just used for unit testing */
146 190
 static int mod_init(void) {
147 191
 	return 0;
... ...
@@ -26,6 +26,7 @@
26 26
 #include <limits.h>
27 27
 
28 28
 #include "../../core/lvalue.h"
29
+#include "../../core/xavp.h"
29 30
 
30 31
 #include "jansson_utils.h"
31 32
 
... ...
@@ -81,3 +82,53 @@ int jansson_to_val(pv_value_t* val, char** freeme, json_t* v) {
81 82
 	}
82 83
 	return 0;
83 84
 }
85
+
86
+int jansson_to_xval(sr_xval_t *val, char** freeme, json_t* v) {
87
+	if(json_is_object(v) || json_is_array(v)) {
88
+		const char* value = json_dumps(v, JSON_COMPACT|JSON_PRESERVE_ORDER);
89
+		*freeme = (char*)value;
90
+		val->type = SR_XTYPE_STR;
91
+		val->v.s.s = (char*)value;
92
+		val->v.s.len = strlen(value);
93
+	}else if(json_is_string(v)) {
94
+		const char* value = json_string_value(v);
95
+		val->type = SR_XTYPE_STR;
96
+		val->v.s.s = (char*)value;
97
+		val->v.s.len = strlen(value);
98
+	}else if(json_is_boolean(v)) {
99
+		val->type = SR_XTYPE_INT;
100
+		val->v.i = json_is_true(v) ? 0 : 1;
101
+	}else if(json_is_real(v)) {
102
+		char* value = NULL;
103
+		if(asprintf(&value, "%.15g", json_real_value(v))<0) {
104
+			ERR("asprintf failed\n");
105
+			return -1;
106
+		}
107
+		*freeme = value;
108
+		val->type = SR_XTYPE_STR;
109
+		val->v.s.s = value;
110
+		val->v.s.len = strlen(value);
111
+	}else if(json_is_integer(v)) {
112
+		long long value = json_integer_value(v);
113
+		if ((value > INT_MAX) || (value < INT_MIN))  {
114
+			char* svalue = NULL;
115
+			if (asprintf(&svalue, "%"JSON_INTEGER_FORMAT, value) < 0) {
116
+				ERR("asprintf failed\n");
117
+				return -1;
118
+			}
119
+			*freeme = svalue;
120
+			val->type = SR_XTYPE_STR;
121
+			val->v.s.s = svalue;
122
+			val->v.s.len = strlen(svalue);
123
+		} else {
124
+			val->type = SR_XTYPE_INT;
125
+			val->v.i = (int)value;
126
+		}
127
+	}else if(json_is_null(v)) {
128
+		val->type = SR_XTYPE_NULL;
129
+	}else {
130
+		ERR("unrecognized json type: %d\n", json_typeof(v));
131
+		return -1;
132
+	}
133
+	return 0;
134
+}
... ...
@@ -27,8 +27,10 @@
27 27
 
28 28
 #include "../../core/sr_module.h"
29 29
 #include "../../core/lvalue.h"
30
+#include "../../core/xavp.h"
30 31
 
31 32
 typedef int (*jansson_to_val_f)(pv_value_t* val, char** freeme, json_t* v);
32 33
 int jansson_to_val(pv_value_t* val, char** freeme, json_t* v);
34
+int jansson_to_xval(sr_xval_t *val, char** freeme, json_t* v);
33 35
 
34 36
 #endif