Browse code

pv: new transformation class {val}

- {val.n0} - return int 0 instead of $null value, or existing value
- {val.json} - if value is $null, return empty string; if value is
string, then it is escaped for use as json value (without surrounding
quotes)

Daniel-Constantin Mierla authored on 17/11/2021 16:16:17
Showing 2 changed files
... ...
@@ -2521,6 +2521,76 @@ int tr_eval_urialias(struct sip_msg *msg, tr_param_t *tp, int subtype,
2521 2521
 }
2522 2522
 
2523 2523
 
2524
+/*!
2525
+ * \brief Evaluate val transformations
2526
+ * \param msg SIP message
2527
+ * \param tp transformation
2528
+ * \param subtype transformation type
2529
+ * \param val pseudo-variable
2530
+ * \return 0 on success, -1 on error
2531
+ */
2532
+int tr_eval_val(struct sip_msg *msg, tr_param_t *tp, int subtype,
2533
+		pv_value_t *val)
2534
+{
2535
+	str sv;
2536
+	int emode = 0;
2537
+
2538
+	if(val==NULL)
2539
+		return -1;
2540
+
2541
+	switch(subtype)
2542
+	{
2543
+		case TR_VAL_N0:
2544
+			if(val->flags&PV_VAL_NULL) {
2545
+				val->ri = 0;
2546
+				tr_set_crt_buffer();
2547
+				val->rs.s = _tr_buffer;
2548
+				val->rs.s[0] = '0';
2549
+				val->rs.s[1] = '\0';
2550
+				val->rs.len = 1;
2551
+				val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
2552
+			}
2553
+			break;
2554
+		case TR_VAL_JSON:
2555
+			if(val->flags&PV_VAL_NULL) {
2556
+				val->ri = 0;
2557
+				tr_set_crt_buffer();
2558
+				val->rs.s = _tr_buffer;
2559
+				val->rs.s[0] = '\0';
2560
+				val->rs.len = 0;
2561
+				val->flags = PV_VAL_STR;
2562
+			} else if(val->flags&PV_VAL_STR) {
2563
+				ksr_str_json_escape(&val->rs, &sv, &emode);
2564
+				if(sv.s==NULL) {
2565
+					LM_ERR("failed to escape the value\n");
2566
+					return -1;
2567
+				}
2568
+				if(emode==0) {
2569
+					/* no escape was needed */
2570
+					return 0;
2571
+				}
2572
+				if(sv.len >= TR_BUFFER_SIZE - 1) {
2573
+					LM_ERR("escaped value is too long\n");
2574
+					return -1;
2575
+				}
2576
+				tr_set_crt_buffer();
2577
+				memcpy(_tr_buffer, sv.s, sv.len);
2578
+				_tr_buffer[sv.len] = '\0';
2579
+				val->rs.s = _tr_buffer;
2580
+				val->rs.len = sv.len;
2581
+			}
2582
+			break;
2583
+
2584
+		default:
2585
+			LM_ERR("unknown subtype %d\n",
2586
+					subtype);
2587
+			return -1;
2588
+	}
2589
+
2590
+	return 0;
2591
+}
2592
+
2593
+
2524 2594
 #define _tr_parse_nparam(_p, _p0, _tp, _spec, _n, _sign, _in, _s) \
2525 2595
 	while(is_in_str(_p, _in) && (*_p==' ' || *_p=='\t' || *_p=='\n')) _p++; \
2526 2596
 	if(*_p==PV_MARKER) \
... ...
@@ -3717,6 +3787,56 @@ char* tr_parse_urialias(str* in, trans_t *t)
3717 3787
 	}
3718 3788
 
3719 3789
 
3790
+	LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
3791
+			name.len, name.s, name.len);
3792
+error:
3793
+	return NULL;
3794
+
3795
+done:
3796
+	t->name = name;
3797
+	return p;
3798
+}
3799
+
3800
+
3801
+/*!
3802
+ * \brief Helper fuction to parse val transformation
3803
+ * \param in parsed string
3804
+ * \param t transformation
3805
+ * \return pointer to the end of the transformation in the string - '}', null on error
3806
+ */
3807
+char* tr_parse_val(str* in, trans_t *t)
3808
+{
3809
+	char *p;
3810
+	str name;
3811
+
3812
+
3813
+	if(in==NULL || t==NULL)
3814
+		return NULL;
3815
+
3816
+	p = in->s;
3817
+	name.s = in->s;
3818
+	t->type = TR_VAL;
3819
+	t->trf = tr_eval_val;
3820
+
3821
+	/* find next token */
3822
+	while(is_in_str(p, in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
3823
+	if(*p=='\0') {
3824
+		LM_ERR("invalid transformation: %.*s\n",
3825
+				in->len, in->s);
3826
+		goto error;
3827
+	}
3828
+	name.len = p - name.s;
3829
+	trim(&name);
3830
+
3831
+	if(name.len==2 && strncasecmp(name.s, "n0", 2)==0) {
3832
+		t->subtype = TR_VAL_N0;
3833
+		goto done;
3834
+	} else if(name.len==4 && strncasecmp(name.s, "json", 4)==0) {
3835
+		t->subtype = TR_VAL_JSON;
3836
+		goto done;
3837
+	}
3838
+
3839
+
3720 3840
 	LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
3721 3841
 			name.len, name.s, name.len);
3722 3842
 error:
... ...
@@ -31,7 +31,7 @@
31 31
 
32 32
 
33 33
 enum _tr_type { TR_NONE=0, TR_STRING, TR_URI, TR_PARAMLIST, TR_NAMEADDR,
34
-				TR_TOBODY, TR_LINE, TR_URIALIAS};
34
+				TR_TOBODY, TR_LINE, TR_URIALIAS, TR_VAL};
35 35
 enum _tr_s_subtype {
36 36
 	TR_S_NONE=0, TR_S_LEN, TR_S_INT, TR_S_MD5, TR_S_SHA256, TR_S_SHA384,
37 37
 	TR_S_SHA512, TR_S_SUBSTR, TR_S_SELECT, TR_S_ENCODEHEXA, TR_S_DECODEHEXA,
... ...
@@ -72,6 +72,10 @@ enum _tr_urialias_subtype {
72 72
 	TR_URIALIAS_NONE=0, TR_URIALIAS_ENCODE, TR_URIALIAS_DECODE
73 73
 };
74 74
 
75
+enum _tr_val_subtype {
76
+	TR_VAL_NONE=0, TR_VAL_N0, TR_VAL_JSON
77
+};
78
+
75 79
 
76 80
 char* tr_parse_string(str *in, trans_t *tr);
77 81
 char* tr_parse_uri(str *in, trans_t *tr);
... ...
@@ -80,6 +84,7 @@ char* tr_parse_nameaddr(str *in, trans_t *tr);
80 84
 char* tr_parse_tobody(str* in, trans_t *t);
81 85
 char* tr_parse_line(str* in, trans_t *t);
82 86
 char* tr_parse_urialias(str* in, trans_t *t);
87
+char* tr_parse_val(str* in, trans_t *t);
83 88
 
84 89
 int tr_init_buffers(void);
85 90