9510c405ba283d062124ff25b2f7e8e45d15aa5c
[kamailio] / src / modules / pv / pv_xavp.c
1 /*
2  * Copyright (C) 2009 Daniel-Constantin Mierla (asipto.com)
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <stdio.h>
18
19 #include "../../core/dprint.h"
20 #include "../../core/xavp.h"
21 #include "../../core/pvapi.h"
22 #include "../../core/trim.h"
23 #include "../../core/parser/parse_param.h"
24
25 #include "pv_xavp.h"
26
27 #define PV_FIELD_DELIM ", "
28 #define PV_FIELD_DELIM_LEN (sizeof(PV_FIELD_DELIM) - 1)
29
30 int pv_xavp_get_value(struct sip_msg *msg, pv_param_t *param,
31                 pv_value_t *res, sr_xavp_t *avp)
32 {
33         static char _pv_xavp_buf[128];
34         str s;
35
36         switch(avp->val.type) {
37                 case SR_XTYPE_NULL:
38                         return pv_get_null(msg, param, res);
39                 break;
40                 case SR_XTYPE_INT:
41                         return pv_get_sintval(msg, param, res, avp->val.v.i);
42                 break;
43                 case SR_XTYPE_STR:
44                         return pv_get_strval(msg, param, res, &avp->val.v.s);
45                 break;
46                 case SR_XTYPE_TIME:
47                         if(snprintf(_pv_xavp_buf, 128, "%lu", (long unsigned)avp->val.v.t)<0)
48                                 return pv_get_null(msg, param, res);
49                 break;
50                 case SR_XTYPE_LONG:
51                         if(snprintf(_pv_xavp_buf, 128, "%ld", (long unsigned)avp->val.v.l)<0)
52                                 return pv_get_null(msg, param, res);
53                 break;
54                 case SR_XTYPE_LLONG:
55                         if(snprintf(_pv_xavp_buf, 128, "%lld", avp->val.v.ll)<0)
56                                 return pv_get_null(msg, param, res);
57                 break;
58                 case SR_XTYPE_XAVP:
59                         if(snprintf(_pv_xavp_buf, 128, "<<xavp:%p>>", avp->val.v.xavp)<0)
60                                 return pv_get_null(msg, param, res);
61                 break;
62                 case SR_XTYPE_VPTR:
63                         if(snprintf(_pv_xavp_buf, 128, "<<vptr:%p>>", avp->val.v.vptr)<0)
64                                 return pv_get_null(msg, param, res);
65                 break;
66                 case SR_XTYPE_SPTR:
67                         if(snprintf(_pv_xavp_buf, 128, "<<sptr:%p>>", avp->val.v.vptr)<0)
68                                 return pv_get_null(msg, param, res);
69                 break;
70                 case SR_XTYPE_DATA:
71                         if(snprintf(_pv_xavp_buf, 128, "<<data:%p>>", avp->val.v.data)<0)
72                                 return pv_get_null(msg, param, res);
73                 break;
74                 default:
75                         return pv_get_null(msg, param, res);
76         }
77         s.s = _pv_xavp_buf;
78         s.len = strlen(_pv_xavp_buf);
79         return pv_get_strval(msg, param, res, &s);
80 }
81
82
83 int pv_get_xavp(struct sip_msg *msg, pv_param_t *param,
84                 pv_value_t *res)
85 {
86         pv_xavp_name_t *xname=NULL;
87         sr_xavp_t *avp=NULL;
88         int idxf = 0;
89         int idx = 0;
90         int count;
91         char *p, *p_ini;
92         int p_size;
93
94         if(param==NULL)
95         {
96                 LM_ERR("bad parameters\n");
97                 return -1;
98         }
99         xname = (pv_xavp_name_t*)param->pvn.u.dname;
100
101         if(xname->index.type==PVT_EXTRA)
102         {
103                 /* get the index */
104                 if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0)
105                 {
106                         LM_ERR("invalid index\n");
107                         return -1;
108                 }
109         }
110         /* fix the index */
111         if(idx<0)
112         {
113                 count = xavp_count(&xname->name, NULL);
114                 idx = count + idx;
115         }
116         avp = xavp_get_by_index(&xname->name, idx, NULL);
117         if(avp==NULL)
118                 return pv_get_null(msg, param, res);
119         if(xname->next==NULL)
120                 return pv_xavp_get_value(msg, param, res, avp);
121         if(avp->val.type != SR_XTYPE_XAVP)
122                 return pv_get_null(msg, param, res);
123
124         idx = 0;
125         idxf = 0;
126         if(xname->next->index.type==PVT_EXTRA)
127         {
128                 /* get the index */
129                 if(pv_get_spec_index(msg, &xname->next->index.pvp, &idx, &idxf)!=0)
130                 {
131                         LM_ERR("invalid index\n");
132                         return -1;
133                 }
134         }
135         /* fix the index */
136         if(idx<0)
137         {
138                 count = xavp_count(&xname->next->name, &avp->val.v.xavp);
139                 idx = count + idx;
140         }
141         avp = xavp_get_by_index(&xname->next->name, idx, &avp->val.v.xavp);
142         if(avp==NULL)
143                 return pv_get_null(msg, param, res);
144         /* get all values of second key */
145         if(idxf==PV_IDX_ALL)
146         {
147                 p_ini = pv_get_buffer();
148                 p = p_ini;
149                 p_size = pv_get_buffer_size();
150                 do {
151                         if(p!=p_ini)
152                         {
153                                 if(p-p_ini+PV_FIELD_DELIM_LEN+1>p_size)
154                                 {
155                                         LM_ERR("local buffer length exceeded\n");
156                                         return pv_get_null(msg, param, res);
157                                 }
158                                 memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
159                                 p += PV_FIELD_DELIM_LEN;
160                         }
161                         if(pv_xavp_get_value(msg, param, res, avp)<0)
162                         {
163                                 LM_ERR("can get value\n");
164                                 return pv_get_null(msg, param, res);
165                         }
166                         if(p-p_ini+res->rs.len+1>p_size)
167                         {
168                                 LM_ERR("local buffer length exceeded!\n");
169                                 return pv_get_null(msg, param, res);
170                         }
171                         memcpy(p, res->rs.s, res->rs.len);
172                         p += res->rs.len;
173                 } while ((avp=xavp_get_next(avp))!=0);
174                 res->rs.s = p_ini;
175                 res->rs.len = p - p_ini;
176                 return 0;
177         }
178         return pv_xavp_get_value(msg, param, res, avp);
179 }
180
181 /**
182  * $xavp(name1[idx1]=>name2[idx2])
183  */
184 int pv_set_xavp(struct sip_msg* msg, pv_param_t *param,
185                 int op, pv_value_t *val)
186 {
187         pv_xavp_name_t *xname=NULL;
188         sr_xavp_t *avp=NULL;
189         sr_xavp_t *list=NULL;
190         sr_xval_t xval;
191         int idxf = 0;
192         int idx = 0;
193         int idxf1 = 0;
194         int idx1 = 0;
195         int count;
196
197         if(param==NULL)
198         {
199                 LM_ERR("bad parameters\n");
200                 return -1;
201         }
202         xname = (pv_xavp_name_t*)param->pvn.u.dname;
203
204         if(xname->index.type==PVT_EXTRA)
205         {
206                 /* get the index */
207                 if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0)
208                 {
209                         LM_ERR("invalid index\n");
210                         return -1;
211                 }
212         }
213
214         if((val==NULL) || (val->flags&PV_VAL_NULL))
215         {
216                 if(xname->next==NULL)
217                 {
218                         if(xname->index.type==PVT_EXTRA) {
219                                 if(idxf==PV_IDX_ALL) {
220                                         xavp_rm_by_name(&xname->name, 1, NULL);
221                                         return 0;
222                                 }
223                         }
224                         if(idx==0) {
225                                 xavp_rm_by_name(&xname->name, 0, NULL);
226                                 return 0;
227                         }
228                         /* fix the index */
229                         if(idx<0)
230                         {
231                                 count = xavp_count(&xname->name, NULL);
232                                 idx = count + idx + 1;
233                         }
234                         xavp_rm_by_index(&xname->name, idx, NULL);
235                         return 0;
236                 }
237                 
238                 if(xname->next->index.type==PVT_EXTRA)
239                 {
240                         /* get the index */
241                         if(pv_get_spec_index(msg,&xname->next->index.pvp,&idx1,&idxf1)!=0)
242                         {
243                                 LM_ERR("invalid index!\n");
244                                 return -1;
245                         }
246                 }
247
248                 if(idxf==PV_IDX_ALL) {
249                         /* iterate */
250                         avp = xavp_get(&xname->name, NULL);
251                         while(avp) {
252                                 if(avp->val.type==SR_XTYPE_XAVP) {
253                                         if(xname->next->index.type==PVT_EXTRA) {
254                                                 if(idxf1==PV_IDX_ALL) {
255                                                         xavp_rm_by_name(&xname->next->name, 1,
256                                                                         &avp->val.v.xavp);
257                                                 } else {
258                                                         /* fix the index */
259                                                         idx = idx1;
260                                                         if(idx<0)
261                                                         {
262                                                                 count = xavp_count(&xname->next->name,
263                                                                                 &avp->val.v.xavp);
264                                                                 idx = count + idx1 + 1;
265                                                         }
266                                                         xavp_rm_by_index(&xname->next->name, idx,
267                                                                         &avp->val.v.xavp);
268                                                 }
269                                         } else {
270                                                 xavp_rm_by_name(&xname->next->name, 0,
271                                                                 &avp->val.v.xavp);
272                                         }
273                                 }
274                                 avp = xavp_get_next(avp);
275                         }
276                         return 0;
277                 }
278
279                 if(idx==0) {
280                         avp = xavp_get(&xname->name, NULL);
281                 } else {
282                         /* fix the index */
283                         if(idx<0)
284                         {
285                                 count = xavp_count(&xname->name, NULL);
286                                 idx = count + idx + 1;
287                         }
288                         avp = xavp_get_by_index(&xname->name, idx, NULL);
289                 }
290                 if(avp) {
291                         if(avp->val.type==SR_XTYPE_XAVP) {
292                                 if(xname->next->index.type==PVT_EXTRA) {
293                                         if(idxf1==PV_IDX_ALL) {
294                                                 xavp_rm_by_name(&xname->next->name, 1,
295                                                                 &avp->val.v.xavp);
296                                         } else {
297                                                 /* fix the index */
298                                                 idx = idx1;
299                                                 if(idx<0)
300                                                 {
301                                                         count = xavp_count(&xname->next->name,
302                                                                         &avp->val.v.xavp);
303                                                         idx = count + idx1 + 1;
304                                                 }
305                                                 xavp_rm_by_index(&xname->next->name, idx,
306                                                                 &avp->val.v.xavp);
307                                         }
308                                 } else {
309                                         xavp_rm_by_name(&xname->next->name, 0,
310                                                         &avp->val.v.xavp);
311                                 }
312                         }
313                 }
314                 return 0;
315         } /* NULL assignment */
316
317         /* build xavp value */
318         memset(&xval, 0, sizeof(sr_xval_t));
319
320         if(val->flags&PV_TYPE_INT)
321         {
322                 xval.type = SR_XTYPE_INT;
323                 xval.v.i = val->ri;
324         } else {
325                 xval.type = SR_XTYPE_STR;
326                 xval.v.s = val->rs;
327         }
328
329         /* where to add */
330         if(xname->next==NULL)
331         {
332                 /* xavp with single value */
333                 if(xname->index.type==PVT_EXTRA) {
334                         if(idxf==PV_IDX_ALL) {
335                                 /* ignore: should iterate and set same value to all xavps
336                                  * with same name?!?! */
337                                 return -1;
338                         }
339                         /* fix the index */
340                         if(idx<0)
341                         {
342                                 count = xavp_count(&xname->name, NULL);
343                                 idx = count + idx + 1;
344                         }
345                         /* set the value */
346                         if(xavp_set_value(&xname->name, idx, &xval, NULL)==NULL)
347                                 return -1;
348                         return 0;
349                 }
350                 /* add new value */
351                 if(xavp_add_value(&xname->name, &xval, NULL)==NULL)
352                         return -1;
353                 return 0;
354         }
355                 
356         /* xavp with xavp list value */
357         if(xname->next->index.type==PVT_EXTRA)
358         {
359                 /* get the index */
360                 if(pv_get_spec_index(msg,&xname->next->index.pvp,&idx1,&idxf1)!=0)
361                 {
362                         LM_ERR("invalid index!\n");
363                         return -1;
364                 }
365         }
366
367         if(xname->index.type==PVT_EXTRA)
368         {
369                 /* set the value */
370                 if(idxf==PV_IDX_ALL) {
371                         /* ignore: should iterate and set same value to all xavps
372                          * with same name?!?! */
373                         return 0;
374                 }
375
376                 if(idx==0) {
377                         avp = xavp_get(&xname->name, NULL);
378                 } else {
379                         /* fix the index */
380                         if(idx<0)
381                         {
382                                 count = xavp_count(&xname->name, NULL);
383                                 idx = count + idx + 1;
384                         }
385                         avp = xavp_get_by_index(&xname->name, idx, NULL);
386                 }
387                 if(avp==NULL)
388                         return 0;
389
390                 if(avp->val.type!=SR_XTYPE_XAVP)
391                         return -1;
392                         
393                 if(xname->next->index.type==PVT_EXTRA) {
394                         if(idxf1==PV_IDX_ALL) {
395                                 /* ignore: should iterate and set same value to all xavps
396                                  * with same name?!?! */
397                                 return 0;
398                         }
399                         /* fix the index */
400                         idx = idx1;
401                         if(idx<0)
402                         {
403                                 count = xavp_count(&xname->next->name,
404                                                 &avp->val.v.xavp);
405                                 idx = count + idx1 + 1;
406                         }
407                         /* set value */
408                         xavp_set_value(&xname->next->name, idx, &xval, &avp->val.v.xavp);
409                         return 0;
410                 }
411                 /* add new value in sublist */
412                 if(xavp_add_value(&xname->next->name, &xval, &avp->val.v.xavp)==NULL)
413                         return -1;
414                 return 0;
415         }
416         /* add new xavp with xavp list */
417         if(xavp_add_value(&xname->next->name, &xval, &list)==NULL)
418                 return -1;
419         
420         /* build xavp value */
421         memset(&xval, 0, sizeof(sr_xval_t));
422         xval.type = SR_XTYPE_XAVP;
423         xval.v.xavp = list;
424         xavp_add_value(&xname->name, &xval, NULL);
425
426         return 0;
427 }
428
429 char* pv_xavp_fill_ni(str *in, pv_xavp_name_t *xname)
430 {
431         char *p;
432         str idx;
433         int n;
434
435         if(in->s==NULL || in->len<=0 || xname==NULL)
436                 return NULL;
437         p = in->s;
438
439         /* eat ws */
440         while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
441                 p++;
442         if(p>in->s+in->len || *p=='\0')
443                 goto error;
444         xname->name.s = p;
445         while(p < in->s + in->len)
446         {
447                 if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r' || *p=='[')
448                         break;
449                 p++;
450         }
451         xname->name.len = p - xname->name.s;
452         if(p>in->s+in->len || *p=='\0')
453                 return p;
454         /* eat ws */
455         while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
456                 p++;
457         if(p>in->s+in->len || *p=='\0')
458                 return p;
459
460         if(*p!='[')
461                 return p;
462         /* there is index */
463         p++;
464         idx.s = p;
465         n = 0;
466         while(p<in->s+in->len && *p!='\0')
467         {
468                 if(*p==']')
469                 {
470                         if(n==0)
471                                 break;
472                         n--;
473                 }
474                 if(*p == '[')
475                         n++;
476                 p++;
477         }
478         if(p>in->s+in->len || *p=='\0')
479                 goto error;
480
481         if(p==idx.s)
482         {
483                 LM_ERR("xavp [\"%.*s\"] does not get empty index param\n",
484                                 in->len, in->s);
485                 goto error;
486         }
487         idx.len = p - idx.s;
488         if(pv_parse_index(&xname->index, &idx)!=0)
489         {
490                 LM_ERR("idx \"%.*s\" has an invalid index param [%.*s]\n",
491                                         in->len, in->s, idx.len, idx.s);
492                 goto error;
493         }
494         xname->index.type = PVT_EXTRA;
495         p++;
496         return p;
497 error:
498         return NULL;
499 }
500
501 void pv_xavp_name_destroy(pv_xavp_name_t *xname)
502 {
503         return;
504 }
505
506 int pv_parse_xavp_name(pv_spec_p sp, str *in)
507 {
508         pv_xavp_name_t *xname=NULL;
509         char *p;
510         str s;
511
512         if(in->s==NULL || in->len<=0)
513                 return -1;
514
515         xname = (pv_xavp_name_t*)pkg_malloc(sizeof(pv_xavp_name_t));
516         if(xname==NULL) {
517                 LM_ERR("not enough pkg mem\n");
518                 return -1;
519         }
520
521         memset(xname, 0, sizeof(pv_xavp_name_t));
522
523         s = *in;
524
525         p = pv_xavp_fill_ni(&s, xname);
526         if(p==NULL)
527                 goto error;
528
529         if(*p!='=')
530                 goto done;
531         p++;
532         if(*p!='>')
533                 goto error;
534         p++;
535
536         s.len = in->len - (int)(p - in->s);
537         s.s = p;
538         LM_DBG("xavp sublist [%.*s] - key [%.*s]\n", xname->name.len,
539                         xname->name.s, s.len, s.s);
540
541         xname->next = (pv_xavp_name_t*)pkg_malloc(sizeof(pv_xavp_name_t));
542         if(xname->next==NULL) {
543                 LM_ERR("not enough pkg mem\n");
544                 goto error;
545         }
546         memset(xname->next, 0, sizeof(pv_xavp_name_t));
547
548         p = pv_xavp_fill_ni(&s, xname->next);
549         if(p==NULL)
550                 goto error;
551
552 done:
553         sp->pvp.pvn.u.dname = (void*)xname;
554         sp->pvp.pvn.type = PV_NAME_PVAR;
555         return 0;
556
557 error:
558         if(xname!=NULL) {
559                 pv_xavp_name_destroy(xname);
560                 pkg_free(xname);
561         }
562         return -1;
563 }
564
565 int pv_xavp_print(sip_msg_t* msg, char* s1, char *s2)
566 {
567         xavp_print_list(NULL);
568         return 1;
569 }
570
571 int pv_xavu_print(sip_msg_t* msg, char* s1, char *s2)
572 {
573         xavu_print_list(NULL);
574         return 1;
575 }
576
577 int pv_xavi_print(sip_msg_t* msg, char* s1, char *s2)
578 {
579         xavi_print_list(NULL);
580         return 1;
581 }
582
583 /**
584  *
585  */
586 int xavp_params_explode(str *params, str *xname)
587 {
588         param_t* params_list = NULL;
589         param_hooks_t phooks;
590         param_t *pit=NULL;
591         str s;
592         sr_xavp_t *xavp=NULL;
593         sr_xval_t xval;
594
595         if(params==NULL || xname==NULL || params->s==NULL || xname->s==NULL
596                         || params->len<=0 || xname->len<=0)
597         {
598                 LM_ERR("invalid parameters\n");
599                 return -1;
600         }
601
602         s.s = params->s;
603         s.len = params->len;
604         if(s.s[s.len-1]==';')
605                 s.len--;
606         if (parse_params(&s, CLASS_ANY, &phooks, &params_list)<0) {
607                 LM_DBG("invalid formatted values [%.*s]\n", params->len, params->s);
608                 return -1;
609         }
610
611         if(params_list==NULL) {
612                 return -1;
613         }
614
615
616         for (pit = params_list; pit; pit=pit->next)
617         {
618                 memset(&xval, 0, sizeof(sr_xval_t));
619                 xval.type = SR_XTYPE_STR;
620                 xval.v.s = pit->body;
621                 if(xavp_add_value(&pit->name, &xval, &xavp)==NULL) {
622                         free_params(params_list);
623                         xavp_destroy_list(&xavp);
624                         return -1;
625                 }
626         }
627         free_params(params_list);
628
629         /* add main xavp in root list */
630         memset(&xval, 0, sizeof(sr_xval_t));
631         xval.type = SR_XTYPE_XAVP;
632         xval.v.xavp = xavp;
633         if(xavp_add_value(xname, &xval, NULL)==NULL) {
634                 xavp_destroy_list(&xavp);
635                 return -1;
636         }
637
638         return 0;
639 }
640
641 int pv_var_to_xavp(str *varname, str *xname)
642 {
643         script_var_t *it;
644         sr_xavp_t *avp = NULL;
645         sr_xval_t xval;
646
647         LM_DBG("xname:%.*s varname:%.*s\n", xname->len, xname->s,
648                 varname->len, varname->s);
649
650         // clean xavp
651         xavp_rm_by_name(xname, 1, NULL);
652
653         if(varname->len==1 && varname->s[0] == '*') {
654                 for(it=get_var_all(); it; it=it->next) {
655                         memset(&xval, 0, sizeof(sr_xval_t));
656                         if(it->v.flags==VAR_VAL_INT)
657                         {
658                                 xval.type = SR_XTYPE_INT;
659                                 xval.v.i = it->v.value.n;
660                                 LM_DBG("[%.*s]: %d\n", it->name.len, it->name.s, xval.v.i);
661                         } else {
662                                 if(it->v.value.s.len==0) continue;
663                                 xval.type = SR_XTYPE_STR;
664                                 xval.v.s.s = it->v.value.s.s;
665                                 xval.v.s.len = it->v.value.s.len;
666                                 LM_DBG("[%.*s]: '%.*s'\n", it->name.len, it->name.s,
667                                         xval.v.s.len, xval.v.s.s);
668                         }
669                         if(xavp_add_value(&it->name, &xval, &avp)==NULL) {
670                                 LM_ERR("can't copy [%.*s]\n", it->name.len, it->name.s);
671                                 goto error;
672                         }
673                 }
674                 if(avp) {
675                         memset(&xval, 0, sizeof(sr_xval_t));
676                         xval.type = SR_XTYPE_XAVP;
677                         xval.v.xavp = avp;
678                         if(xavp_add_value(xname, &xval, NULL)==NULL) {
679                                 LM_ERR("Can't create xavp[%.*s]\n", xname->len, xname->s);
680                                 goto error;
681                         }
682                 }
683         }
684         else {
685                 it = get_var_by_name(varname);
686                 if(it==NULL) {
687                         LM_ERR("script var [%.*s] not found\n", varname->len, varname->s);
688                         return -1;
689                 }
690                 memset(&xval, 0, sizeof(sr_xval_t));
691                 if(it->v.flags==VAR_VAL_INT)
692                 {
693                         xval.type = SR_XTYPE_INT;
694                         xval.v.i = it->v.value.n;
695                         LM_DBG("[%.*s]: %d\n", it->name.len, it->name.s, xval.v.i);
696                 } else {
697                         xval.type = SR_XTYPE_STR;
698                         xval.v.s.s = it->v.value.s.s;
699                         xval.v.s.len = it->v.value.s.len;
700                         LM_DBG("[%.*s]: '%.*s'\n", it->name.len, it->name.s,
701                                         xval.v.s.len, xval.v.s.s);
702                 }
703                 if(xavp_add_xavp_value(xname, &it->name, &xval, NULL)==NULL) {
704                         LM_ERR("can't copy [%.*s]\n", it->name.len, it->name.s);
705                         return -1;
706                 }
707         }
708         return 1;
709
710 error:
711         if(avp) xavp_destroy_list(&avp);
712         return -1;
713 }
714
715 int pv_xavp_to_var_helper(sr_xavp_t *avp) {
716         script_var_t *it;
717         int_str value;
718         int flags = 0;
719
720         it = add_var(&avp->name, VAR_TYPE_ZERO);
721         if(!it) return -1;
722         if(avp->val.type==SR_XTYPE_STR){
723                 flags |= VAR_VAL_STR;
724                 value.s.len = avp->val.v.s.len;
725                 value.s.s = avp->val.v.s.s;
726                 LM_DBG("var:[%.*s] STR:[%.*s]\n", avp->name.len, avp->name.s,
727                         value.s.len, value.s.s);
728         }
729         else if(avp->val.type==SR_XTYPE_INT) {
730                 flags |= VAR_VAL_INT;
731                 value.n = avp->val.v.i;
732                 LM_DBG("var:[%.*s] INT:[%d]\n", avp->name.len, avp->name.s,
733                         value.n);
734         } else {
735                 LM_ERR("avp type not STR nor INT\n");
736                 return -1;
737         }
738         set_var_value(it, &value, flags);
739
740         return 0;
741 }
742
743 int pv_xavp_to_var(str *xname) {
744         sr_xavp_t *xavp;
745         sr_xavp_t *avp;
746
747         LM_DBG("xname:%.*s\n", xname->len, xname->s);
748
749         xavp = xavp_get_by_index(xname, 0, NULL);
750         if(!xavp) {
751                 LM_ERR("xavp [%.*s] not found\n", xname->len, xname->s);
752                 return -1;
753         }
754         if(xavp->val.type!=SR_XTYPE_XAVP){
755                 LM_ERR("%.*s not xavp type?\n", xname->len, xname->s);
756                 return -1;
757         }
758         do {
759                 avp = xavp->val.v.xavp;
760                 if (avp)
761                 {
762                         if(pv_xavp_to_var_helper(avp)<0) return -1;
763                         avp = avp->next;
764                 }
765
766                 while(avp)
767                 {
768                         if(pv_xavp_to_var_helper(avp)<0) return -1;
769                         avp = avp->next;
770                 }
771                 xavp = xavp_get_next(xavp);
772         } while(xavp);
773         return 1;
774 }
775
776 void pv_xavu_name_destroy(pv_xavu_name_t *xname)
777 {
778         return;
779 }
780
781 int pv_parse_xavu_name(pv_spec_t *sp, str *in)
782 {
783         pv_xavu_name_t *xname=NULL;
784         str s;
785         int i;
786
787         if(in->s==NULL || in->len<=0)
788                 return -1;
789
790         xname = (pv_xavu_name_t*)pkg_malloc(sizeof(pv_xavu_name_t));
791         if(xname==NULL) {
792                 LM_ERR("not enough pkg mem\n");
793                 return -1;
794         }
795
796         memset(xname, 0, sizeof(pv_xavu_name_t));
797
798         s = *in;
799         trim(&s);
800         xname->name.s = s.s;
801         xname->name.len = s.len;
802         for(i=0; i<s.len; i++) {
803                 if(s.s[i] == '=') {
804                         break;
805                 }
806         }
807         if(i==s.len) {
808                 goto done;
809         }
810         if(i>=s.len-2) {
811                 goto error;
812         }
813         xname->name.len = i;
814
815         i++;
816         if(s.s[i]!='>') {
817                 goto error;
818         }
819         i++;
820
821         LM_DBG("xavp sublist [%.*s] - key [%.*s]\n", xname->name.len,
822                         xname->name.s, s.len - i, s.s + i);
823
824         xname->next = (pv_xavu_name_t*)pkg_malloc(sizeof(pv_xavu_name_t));
825         if(xname->next==NULL) {
826                 LM_ERR("not enough pkg mem\n");
827                 goto error;
828         }
829         memset(xname->next, 0, sizeof(pv_xavu_name_t));
830
831         xname->next->name.s = s.s + i;
832         xname->next->name.len = s.len - i;
833
834 done:
835         sp->pvp.pvn.u.dname = (void*)xname;
836         sp->pvp.pvn.type = PV_NAME_PVAR;
837         return 0;
838
839 error:
840         if(xname!=NULL) {
841                 pv_xavu_name_destroy(xname);
842                 pkg_free(xname);
843         }
844         return -1;
845 }
846
847 int pv_get_xavu(struct sip_msg *msg, pv_param_t *param,
848                 pv_value_t *res)
849 {
850         pv_xavu_name_t *xname=NULL;
851         sr_xavp_t *avu=NULL;
852
853         if(param==NULL) {
854                 LM_ERR("bad parameters\n");
855                 return -1;
856         }
857         xname = (pv_xavu_name_t*)param->pvn.u.dname;
858
859         avu = xavu_lookup(&xname->name, NULL);
860         if(avu==NULL) {
861                 return pv_get_null(msg, param, res);
862         }
863         if(xname->next==NULL) {
864                 return pv_xavp_get_value(msg, param, res, avu);
865         }
866         if(avu->val.type != SR_XTYPE_XAVP) {
867                 return pv_get_null(msg, param, res);
868         }
869
870         avu = xavu_lookup(&xname->next->name, &avu->val.v.xavp);
871         if(avu==NULL) {
872                 return pv_get_null(msg, param, res);
873         }
874         return pv_xavp_get_value(msg, param, res, avu);
875 }
876
877 /**
878  * $xavu(name1=>name2)
879  */
880 int pv_set_xavu(struct sip_msg* msg, pv_param_t *param,
881                 int op, pv_value_t *val)
882 {
883         pv_xavu_name_t *xname=NULL;
884         sr_xavp_t *avu=NULL;
885         sr_xval_t xval;
886
887         if(param==NULL) {
888                 LM_ERR("bad parameters\n");
889                 return -1;
890         }
891         xname = (pv_xavu_name_t*)param->pvn.u.dname;
892
893         if((val==NULL) || (val->flags&PV_VAL_NULL)) {
894                 if(xname->next==NULL) {
895                         xavu_rm_by_name(&xname->name, NULL);
896                         return 0;
897                 }
898                 
899                 avu = xavu_lookup(&xname->name, NULL);
900                 if(avu!=NULL && avu->val.type==SR_XTYPE_XAVP) {
901                         xavu_rm_by_name(&xname->next->name, &avu->val.v.xavp);
902                 }
903                 return 0;
904         } /* NULL assignment */
905
906         /* build xavp value */
907         memset(&xval, 0, sizeof(sr_xval_t));
908
909         if(val->flags&PV_TYPE_INT) {
910                 xval.type = SR_XTYPE_INT;
911                 xval.v.i = val->ri;
912         } else {
913                 xval.type = SR_XTYPE_STR;
914                 xval.v.s = val->rs;
915         }
916
917         if(xname->next==NULL) {
918                 /* set root xavu value */
919                 if(xavu_set_xval(&xname->name, &xval, NULL)==NULL) {
920                         return -1;
921                 }
922                 return 0;
923         }
924
925         /* set child xavu value */
926         if(xavu_set_child_xval(&xname->name, &xname->next->name, &xval)==NULL) {
927                 return -1;
928         }
929         return 0;
930 }
931
932 void pv_xavi_name_destroy(pv_xavp_name_t *xname)
933 {
934         return;
935 }
936
937 int pv_parse_xavi_name(pv_spec_p sp, str *in)
938 {
939         pv_xavp_name_t *xname=NULL;
940         char *p;
941         str s;
942
943         if(in->s==NULL || in->len<=0)
944                 return -1;
945
946         xname = (pv_xavp_name_t*)pkg_malloc(sizeof(pv_xavp_name_t));
947         if(xname==NULL) {
948                 PKG_MEM_ERROR;
949                 return -1;
950         }
951
952         memset(xname, 0, sizeof(pv_xavp_name_t));
953
954         s = *in;
955
956         p = pv_xavp_fill_ni(&s, xname);
957         if(p==NULL)
958                 goto error;
959
960         if(*p!='=')
961                 goto done;
962         p++;
963         if(*p!='>')
964                 goto error;
965         p++;
966
967         s.len = in->len - (int)(p - in->s);
968         s.s = p;
969         LM_DBG("xavi sublist [%.*s] - key [%.*s]\n", xname->name.len,
970                         xname->name.s, s.len, s.s);
971
972         xname->next = (pv_xavp_name_t*)pkg_malloc(sizeof(pv_xavp_name_t));
973         if(xname->next==NULL) {
974                 LM_ERR("not enough pkg mem\n");
975                 goto error;
976         }
977         memset(xname->next, 0, sizeof(pv_xavp_name_t));
978
979         p = pv_xavp_fill_ni(&s, xname->next);
980         if(p==NULL)
981                 goto error;
982
983 done:
984         sp->pvp.pvn.u.dname = (void*)xname;
985         sp->pvp.pvn.type = PV_NAME_PVAR;
986         return 0;
987
988 error:
989         if(xname!=NULL) {
990                 pv_xavi_name_destroy(xname);
991                 pkg_free(xname);
992         }
993         return -1;
994 }
995
996 int pv_get_xavi(struct sip_msg *msg, pv_param_t *param,
997                 pv_value_t *res)
998 {
999         pv_xavp_name_t *xname=NULL;
1000         sr_xavp_t *avi=NULL;
1001         int idxf = 0;
1002         int idx = 0;
1003         int count;
1004         char *p, *p_ini;
1005         int p_size;
1006
1007         if(param==NULL)
1008         {
1009                 LM_ERR("bad parameters\n");
1010                 return -1;
1011         }
1012         xname = (pv_xavp_name_t*)param->pvn.u.dname;
1013
1014         if(xname->index.type==PVT_EXTRA)
1015         {
1016                 /* get the index */
1017                 if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0)
1018                 {
1019                         LM_ERR("invalid index\n");
1020                         return -1;
1021                 }
1022         }
1023         /* fix the index */
1024         if(idx<0)
1025         {
1026                 count = xavi_count(&xname->name, NULL);
1027                 idx = count + idx;
1028         }
1029         avi = xavi_get_by_index(&xname->name, idx, NULL);
1030         if(avi==NULL)
1031                 return pv_get_null(msg, param, res);
1032         if(xname->next==NULL)
1033                 return pv_xavp_get_value(msg, param, res, avi);
1034         if(avi->val.type != SR_XTYPE_XAVP)
1035                 return pv_get_null(msg, param, res);
1036
1037         idx = 0;
1038         idxf = 0;
1039         if(xname->next->index.type==PVT_EXTRA)
1040         {
1041                 /* get the index */
1042                 if(pv_get_spec_index(msg, &xname->next->index.pvp, &idx, &idxf)!=0)
1043                 {
1044                         LM_ERR("invalid index\n");
1045                         return -1;
1046                 }
1047         }
1048         /* fix the index */
1049         if(idx<0)
1050         {
1051                 count = xavi_count(&xname->next->name, &avi->val.v.xavp);
1052                 idx = count + idx;
1053         }
1054         avi = xavi_get_by_index(&xname->next->name, idx, &avi->val.v.xavp);
1055         if(avi==NULL)
1056                 return pv_get_null(msg, param, res);
1057         /* get all values of second key */
1058         if(idxf==PV_IDX_ALL)
1059         {
1060                 p_ini = pv_get_buffer();
1061                 p = p_ini;
1062                 p_size = pv_get_buffer_size();
1063                 do {
1064                         if(p!=p_ini)
1065                         {
1066                                 if(p-p_ini+PV_FIELD_DELIM_LEN+1>p_size)
1067                                 {
1068                                         LM_ERR("local buffer length exceeded\n");
1069                                         return pv_get_null(msg, param, res);
1070                                 }
1071                                 memcpy(p, PV_FIELD_DELIM, PV_FIELD_DELIM_LEN);
1072                                 p += PV_FIELD_DELIM_LEN;
1073                         }
1074                         if(pv_xavp_get_value(msg, param, res, avi)<0)
1075                         {
1076                                 LM_ERR("can get value\n");
1077                                 return pv_get_null(msg, param, res);
1078                         }
1079                         if(p-p_ini+res->rs.len+1>p_size)
1080                         {
1081                                 LM_ERR("local buffer length exceeded!\n");
1082                                 return pv_get_null(msg, param, res);
1083                         }
1084                         memcpy(p, res->rs.s, res->rs.len);
1085                         p += res->rs.len;
1086                 } while ((avi=xavi_get_next(avi))!=0);
1087                 res->rs.s = p_ini;
1088                 res->rs.len = p - p_ini;
1089                 return 0;
1090         }
1091         return pv_xavp_get_value(msg, param, res, avi);
1092 }
1093
1094 /**
1095  * $xavi(name1[idx1]=>name2[idx2])
1096  */
1097 int pv_set_xavi(struct sip_msg* msg, pv_param_t *param,
1098                 int op, pv_value_t *val)
1099 {
1100         pv_xavp_name_t *xname=NULL;
1101         sr_xavp_t *avi=NULL;
1102         sr_xavp_t *list=NULL;
1103         sr_xval_t xval;
1104         int idxf = 0;
1105         int idx = 0;
1106         int idxf1 = 0;
1107         int idx1 = 0;
1108         int count;
1109
1110         if(param==NULL)
1111         {
1112                 LM_ERR("bad parameters\n");
1113                 return -1;
1114         }
1115         xname = (pv_xavp_name_t*)param->pvn.u.dname;
1116
1117         if(xname->index.type==PVT_EXTRA)
1118         {
1119                 /* get the index */
1120                 if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0)
1121                 {
1122                         LM_ERR("invalid index\n");
1123                         return -1;
1124                 }
1125         }
1126
1127         if((val==NULL) || (val->flags&PV_VAL_NULL))
1128         {
1129                 if(xname->next==NULL)
1130                 {
1131                         if(xname->index.type==PVT_EXTRA) {
1132                                 if(idxf==PV_IDX_ALL) {
1133                                         xavi_rm_by_name(&xname->name, 1, NULL);
1134                                         return 0;
1135                                 }
1136                         }
1137                         if(idx==0) {
1138                                 xavi_rm_by_name(&xname->name, 0, NULL);
1139                                 return 0;
1140                         }
1141                         /* fix the index */
1142                         if(idx<0)
1143                         {
1144                                 count = xavi_count(&xname->name, NULL);
1145                                 idx = count + idx + 1;
1146                         }
1147                         xavi_rm_by_index(&xname->name, idx, NULL);
1148                         return 0;
1149                 }
1150
1151                 if(xname->next->index.type==PVT_EXTRA)
1152                 {
1153                         /* get the index */
1154                         if(pv_get_spec_index(msg,&xname->next->index.pvp,&idx1,&idxf1)!=0)
1155                         {
1156                                 LM_ERR("invalid index!\n");
1157                                 return -1;
1158                         }
1159                 }
1160
1161                 if(idxf==PV_IDX_ALL) {
1162                         /* iterate */
1163                         avi = xavi_get(&xname->name, NULL);
1164                         while(avi) {
1165                                 if(avi->val.type==SR_XTYPE_XAVP) {
1166                                         if(xname->next->index.type==PVT_EXTRA) {
1167                                                 if(idxf1==PV_IDX_ALL) {
1168                                                         xavi_rm_by_name(&xname->next->name, 1,
1169                                                                         &avi->val.v.xavp);
1170                                                 } else {
1171                                                         /* fix the index */
1172                                                         idx = idx1;
1173                                                         if(idx<0)
1174                                                         {
1175                                                                 count = xavi_count(&xname->next->name,
1176                                                                                 &avi->val.v.xavp);
1177                                                                 idx = count + idx1 + 1;
1178                                                         }
1179                                                         xavi_rm_by_index(&xname->next->name, idx,
1180                                                                         &avi->val.v.xavp);
1181                                                 }
1182                                         } else {
1183                                                 xavi_rm_by_name(&xname->next->name, 0,
1184                                                                 &avi->val.v.xavp);
1185                                         }
1186                                 }
1187                                 avi = xavi_get_next(avi);
1188                         }
1189                         return 0;
1190                 }
1191
1192                 if(idx==0) {
1193                         avi = xavi_get(&xname->name, NULL);
1194                 } else {
1195                         /* fix the index */
1196                         if(idx<0)
1197                         {
1198                                 count = xavi_count(&xname->name, NULL);
1199                                 idx = count + idx + 1;
1200                         }
1201                         avi = xavi_get_by_index(&xname->name, idx, NULL);
1202                 }
1203                 if(avi) {
1204                         if(avi->val.type==SR_XTYPE_XAVP) {
1205                                 if(xname->next->index.type==PVT_EXTRA) {
1206                                         if(idxf1==PV_IDX_ALL) {
1207                                                 xavi_rm_by_name(&xname->next->name, 1,
1208                                                                 &avi->val.v.xavp);
1209                                         } else {
1210                                                 /* fix the index */
1211                                                 idx = idx1;
1212                                                 if(idx<0)
1213                                                 {
1214                                                         count = xavi_count(&xname->next->name,
1215                                                                         &avi->val.v.xavp);
1216                                                         idx = count + idx1 + 1;
1217                                                 }
1218                                                 xavi_rm_by_index(&xname->next->name, idx,
1219                                                                 &avi->val.v.xavp);
1220                                         }
1221                                 } else {
1222                                         xavi_rm_by_name(&xname->next->name, 0,
1223                                                         &avi->val.v.xavp);
1224                                 }
1225                         }
1226                 }
1227                 return 0;
1228         } /* NULL assignment */
1229
1230         /* build xavi value */
1231         memset(&xval, 0, sizeof(sr_xval_t));
1232
1233         if(val->flags&PV_TYPE_INT)
1234         {
1235                 xval.type = SR_XTYPE_INT;
1236                 xval.v.i = val->ri;
1237         } else {
1238                 xval.type = SR_XTYPE_STR;
1239                 xval.v.s = val->rs;
1240         }
1241
1242         /* where to add */
1243         if(xname->next==NULL)
1244         {
1245                 /* xavi with single value */
1246                 if(xname->index.type==PVT_EXTRA) {
1247                         if(idxf==PV_IDX_ALL) {
1248                                 /* ignore: should iterate and set same value to all xavis
1249                                  * with same name?!?! */
1250                                 return -1;
1251                         }
1252                         /* fix the index */
1253                         if(idx<0)
1254                         {
1255                                 count = xavi_count(&xname->name, NULL);
1256                                 idx = count + idx + 1;
1257                         }
1258                         /* set the value */
1259                         if(xavi_set_value(&xname->name, idx, &xval, NULL)==NULL)
1260                                 return -1;
1261                         return 0;
1262                 }
1263                 /* add new value */
1264                 if(xavi_add_value(&xname->name, &xval, NULL)==NULL)
1265                         return -1;
1266                 return 0;
1267         }
1268
1269         /* xavi with xavp list value */
1270         if(xname->next->index.type==PVT_EXTRA)
1271         {
1272                 /* get the index */
1273                 if(pv_get_spec_index(msg,&xname->next->index.pvp,&idx1,&idxf1)!=0)
1274                 {
1275                         LM_ERR("invalid index!\n");
1276                         return -1;
1277                 }
1278         }
1279
1280         if(xname->index.type==PVT_EXTRA)
1281         {
1282                 /* set the value */
1283                 if(idxf==PV_IDX_ALL) {
1284                         /* ignore: should iterate and set same value to all xavis
1285                          * with same name?!?! */
1286                         return 0;
1287                 }
1288
1289                 if(idx==0) {
1290                         avi = xavi_get(&xname->name, NULL);
1291                 } else {
1292                         /* fix the index */
1293                         if(idx<0)
1294                         {
1295                                 count = xavi_count(&xname->name, NULL);
1296                                 idx = count + idx + 1;
1297                         }
1298                         avi = xavi_get_by_index(&xname->name, idx, NULL);
1299                 }
1300                 if(avi==NULL)
1301                         return 0;
1302
1303                 if(avi->val.type!=SR_XTYPE_XAVP)
1304                         return -1;
1305
1306                 if(xname->next->index.type==PVT_EXTRA) {
1307                         if(idxf1==PV_IDX_ALL) {
1308                                 /* ignore: should iterate and set same value to all xavis
1309                                  * with same name?!?! */
1310                                 return 0;
1311                         }
1312                         /* fix the index */
1313                         idx = idx1;
1314                         if(idx<0)
1315                         {
1316                                 count = xavi_count(&xname->next->name,
1317                                                 &avi->val.v.xavp);
1318                                 idx = count + idx1 + 1;
1319                         }
1320                         /* set value */
1321                         xavi_set_value(&xname->next->name, idx, &xval, &avi->val.v.xavp);
1322                         return 0;
1323                 }
1324                 /* add new value in sublist */
1325                 if(xavi_add_value(&xname->next->name, &xval, &avi->val.v.xavp)==NULL)
1326                         return -1;
1327                 return 0;
1328         }
1329         /* add new xavi with xavp list */
1330         if(xavi_add_value(&xname->next->name, &xval, &list)==NULL)
1331                 return -1;
1332
1333         /* build xavi value */
1334         memset(&xval, 0, sizeof(sr_xval_t));
1335         xval.type = SR_XTYPE_XAVP;
1336         xval.v.xavp = list;
1337         xavi_add_value(&xname->name, &xval, NULL);
1338
1339         return 0;
1340 }