Skip to content

Commit

Permalink
transformations/nameaddr: add support for indexes
Browse files Browse the repository at this point in the history
When running the nameaddr transformation on multi-nameaddr headers, one
can specify an index for the nameaddr spec that needs to be used.
The index is optional, the new format is nameddr.[idx.]<subtype>, and if
missing, the first index is returned (0).
  • Loading branch information
razvancrainea committed Dec 22, 2022
1 parent 5d1f5c2 commit b32b7ff
Showing 1 changed file with 88 additions and 16 deletions.
104 changes: 88 additions & 16 deletions transformations.c
Original file line number Diff line number Diff line change
Expand Up @@ -2409,6 +2409,9 @@ int tr_eval_nameaddr(struct sip_msg *msg, tr_param_t *tp, int subtype,
pv_value_t *val)
{
struct to_param* topar;
pv_value_t v;
int index, total;
struct to_body *nameaddr = NULL;

if (!val)
return -1;
Expand Down Expand Up @@ -2458,7 +2461,7 @@ int tr_eval_nameaddr(struct sip_msg *msg, tr_param_t *tp, int subtype,
nameaddr_str.s[0] = 0;
goto error;
}
parse_to(nameaddr_str.s, nameaddr_str.s + nameaddr_str.len,
parse_multi_to(nameaddr_str.s, nameaddr_str.s + nameaddr_str.len,
nameaddr_to_body);
}

Expand All @@ -2468,23 +2471,69 @@ int tr_eval_nameaddr(struct sip_msg *msg, tr_param_t *tp, int subtype,
goto error;
}

/* check if there is an index set */
if (tp && (tp->type != TR_NA_PARAM || tp->next)) {
/* we do have an index */
switch (tp->type) {
case TR_PARAM_NUMBER:
index = tp->v.n;
break;
case TR_PARAM_SPEC:
if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
|| (!(v.flags&PV_VAL_INT)))
{
LM_ERR("invalid index type: %d; integer expected\n",
v.flags);
goto error;
}
index = v.ri;
break;
default:
LM_ERR("invalid index type: %d; integer expected\n",
tp->type);
goto error;
}
tp = tp->next;
if (index < 0) {
total = 0;
for (nameaddr = nameaddr_to_body; nameaddr; nameaddr = nameaddr->next)
total++;
if (index + total < 0) {
LM_DBG("index %d out of bounds %d\n", index, total);
goto out_of_bounds;
}
index = total + index;
}
for (nameaddr = nameaddr_to_body;
nameaddr && index != 0;
nameaddr = nameaddr->next, index--);
if (index > 0 || !nameaddr) {
LM_DBG("index out of bounds\n");
goto out_of_bounds;
}

} else {
/* otherwise we default to first body */
nameaddr = nameaddr_to_body;
}

memset(val, 0, sizeof(pv_value_t));
val->flags = PV_VAL_STR;

switch(subtype)
{
case TR_NA_URI:
val->rs =(nameaddr_to_body->uri.s)?nameaddr_to_body->uri:_tr_empty;
val->rs =(nameaddr->uri.s)?nameaddr->uri:_tr_empty;
val->flags |= (val->rs.len) ? 0 : PV_VAL_NULL;
break;
case TR_NA_LEN:
val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
val->ri = nameaddr_to_body->body.len;
val->ri = nameaddr->body.len;
val->rs.s = int2str(val->ri, &val->rs.len);
break;
case TR_NA_NAME:
val->rs = (nameaddr_to_body->display.s)?
nameaddr_to_body->display:_tr_empty;
val->rs = (nameaddr->display.s)?
nameaddr->display:_tr_empty;
val->flags |= (val->rs.len) ? 0 : PV_VAL_NULL;
break;
case TR_NA_PARAM:
Expand All @@ -2493,7 +2542,7 @@ int tr_eval_nameaddr(struct sip_msg *msg, tr_param_t *tp, int subtype,
LM_ERR("Wrong type for parameter, it must string\n");
goto error;
}
topar = nameaddr_to_body->param_lst;
topar = nameaddr->param_lst;
/* search the parameter */
while(topar)
{
Expand All @@ -2506,20 +2555,20 @@ int tr_eval_nameaddr(struct sip_msg *msg, tr_param_t *tp, int subtype,
val->flags |= (val->rs.len) ? 0 : PV_VAL_NULL;
break;
case TR_NA_PARAMS:
topar = nameaddr_to_body->param_lst;
topar = nameaddr->param_lst;
if (!topar) {
LM_DBG("no params\n");
val->flags = PV_VAL_NULL;
}
else {
LM_DBG("We have params\n");
val->rs.s = topar->name.s;
if (nameaddr_to_body->last_param->value.s==NULL) {
val->rs.len = nameaddr_to_body->last_param->name.s +
nameaddr_to_body->last_param->name.len - val->rs.s;
if (nameaddr->last_param->value.s==NULL) {
val->rs.len = nameaddr->last_param->name.s +
nameaddr->last_param->name.len - val->rs.s;
} else {
val->rs.len = nameaddr_to_body->last_param->value.s +
nameaddr_to_body->last_param->value.len - val->rs.s;
val->rs.len = nameaddr->last_param->value.s +
nameaddr->last_param->value.len - val->rs.s;
/* compensate the len if the value of the last param is
* a quoted value (include the closing quote in the len) */
if ( (val->rs.s+val->rs.len<nameaddr_str.len+nameaddr_str.s) &&
Expand All @@ -2539,6 +2588,9 @@ int tr_eval_nameaddr(struct sip_msg *msg, tr_param_t *tp, int subtype,
error:
val->flags = PV_VAL_NULL;
return -1;
out_of_bounds:
val->flags = PV_VAL_NULL;
return 0;
}


Expand Down Expand Up @@ -2712,7 +2764,7 @@ char *tr_parse_nparam(char *p, str *in, tr_param_t **tp)
(*tp)->type = TR_PARAM_NUMBER;
(*tp)->v.n = sign*n;
} else {
LM_ERR("tinvalid param in transformation: %.*s!!\n",
LM_ERR("invalid param in transformation: %.*s!!\n",
in->len, in->s);
goto error;
}
Expand Down Expand Up @@ -3447,10 +3499,11 @@ int tr_parse_nameaddr(str* in, trans_t *t)
return -1;

p = in->s;
name.s = in->s;
parse_name:
name.s = p;

/* find next token */
while(is_in_str(p, in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
while(is_in_str(p, in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET && *p!=TR_CLASS_MARKER) p++;
if(*p=='\0')
{
LM_ERR("invalid transformation: %.*s\n",
Expand All @@ -3459,6 +3512,22 @@ int tr_parse_nameaddr(str* in, trans_t *t)
}
name.len = p - name.s;
trim(&name);
if (*p == TR_CLASS_MARKER) {
if (t->params) {
LM_ERR("transformation [%.*s] already has an index!\n",
in->len, in->s);
goto error;
}
/* we either have a pvar, or an index */
if (tr_parse_nparam(name.s, &name, &tp) == NULL) {
LM_ERR("invalid index: %.*s\n", name.len, name.s);
goto error;
}
t->params = tp;
tp = 0;
p++;
goto parse_name;
}

if(name.len==3 && strncasecmp(name.s, "uri", 3)==0)
{
Expand All @@ -3482,7 +3551,10 @@ int tr_parse_nameaddr(str* in, trans_t *t)
p++;
if (tr_parse_sparam(p, in, &tp, 0) == NULL)
goto error;
t->params = tp;
if (t->params)
t->params->next = tp;
else
t->params = tp;
tp = 0;

return 0;
Expand Down

0 comments on commit b32b7ff

Please sign in to comment.