msrp: use formated string instead of complex sequence of concatenation
[sip-router] / src / modules / pv / pv_trans.c
1 /*
2  * Copyright (C) 2007 voice-system.ro
3  * Copyright (C) 2009 asipto.com
4  *
5  * This file is part of Kamailio, a free SIP server.
6  *
7  * Kamailio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version
11  *
12  * Kamailio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23 /*! \file
24  * \brief Support for transformations
25  */
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <time.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33
34 #include "../../core/dprint.h"
35 #include "../../core/mem/mem.h"
36 #include "../../core/ut.h"
37 #include "../../core/trim.h"
38 #include "../../core/pvapi.h"
39 #include "../../core/dset.h"
40 #include "../../core/basex.h"
41 #include "../../core/action.h"
42
43 #include "../../core/parser/parse_param.h"
44 #include "../../core/parser/parse_uri.h"
45 #include "../../core/parser/parse_to.h"
46 #include "../../core/parser/parse_nameaddr.h"
47
48 #include "../../core/strutils.h"
49 #include "../../lib/srutils/shautils.h"
50 #include "pv_trans.h"
51
52
53 static char _tr_empty_buf[2] = {0};
54 static str _tr_empty = { _tr_empty_buf, 0 };
55 static str _tr_uri = {0, 0};
56 static struct sip_uri _tr_parsed_uri;
57 static param_t* _tr_uri_params = NULL;
58
59 /*! transformation buffer size */
60 #define TR_BUFFER_SIZE 65536
61 #define TR_BUFFER_SLOTS 4
62
63 /*! transformation buffer */
64 static char **_tr_buffer_list = NULL;
65
66 static char *_tr_buffer = NULL;
67
68 static int _tr_buffer_idx = 0;
69
70 /*!
71  *
72  */
73 int tr_init_buffers(void)
74 {
75         int i;
76
77         _tr_buffer_list = (char**)malloc(TR_BUFFER_SLOTS * sizeof(char*));
78         if(_tr_buffer_list==NULL)
79                 return -1;
80         for(i=0; i<TR_BUFFER_SLOTS; i++) {
81                 _tr_buffer_list[i] = (char*)malloc(TR_BUFFER_SIZE);
82                 if(_tr_buffer_list[i]==NULL)
83                         return -1;
84         }
85         return 0;
86 }
87
88 /*!
89  *
90  */
91 char *tr_set_crt_buffer(void)
92 {
93         _tr_buffer = _tr_buffer_list[_tr_buffer_idx];
94         _tr_buffer_idx = (_tr_buffer_idx + 1) % TR_BUFFER_SLOTS;
95         return _tr_buffer;
96 }
97
98 #define tr_string_clone_result do { \
99                 if(val->rs.len>TR_BUFFER_SIZE-1) { \
100                         LM_ERR("result is too big (cfg line: %d)\n", get_cfg_crt_line()); \
101                         return -1; \
102                 } \
103                 strncpy(_tr_buffer, val->rs.s, val->rs.len); \
104                 val->rs.s = _tr_buffer; \
105         } while(0);
106
107 /* -- helper functions */
108
109 /* Converts a hex character to its integer value */
110 static char pv_from_hex(char ch)
111 {
112         return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
113 }
114
115 /* Converts an integer value to its hex character */
116 static char pv_to_hex(char code)
117 {
118         static char hex[] = "0123456789abcdef";
119         return hex[code & 15];
120 }
121
122 /*! \brief
123  *  URL Encodes a string for use in a HTTP query
124  */
125 static int urlencode_param(str *sin, str *sout)
126 {
127         char *at, *p;
128
129         if (sin==NULL || sout==NULL || sin->s==NULL || sout->s==NULL ||
130                         sin->len<0 || sout->len < 3*sin->len+1)
131                 return -1;
132
133         at = sout->s;
134         p  = sin->s;
135
136         while (p < sin->s+sin->len) {
137                 if (isalnum(*p) || *p == '-' || *p == '_' || *p == '.' || *p == '~')
138                         *at++ = *p;
139                 else if (*p == ' ')
140                         *at++ = '+';
141                 else
142                         *at++ = '%', *at++ = pv_to_hex(*p >> 4), *at++ = pv_to_hex(*p & 15);
143                 p++;
144         }
145
146         *at = 0;
147         sout->len = at - sout->s;
148         LM_DBG("urlencoded string is <%s>\n", sout->s);
149
150         return 0;
151 }
152
153 /* URL Decode a string */
154 static int urldecode_param(str *sin, str *sout) {
155         char *at, *p;
156
157         at = sout->s;
158         p  = sin->s;
159
160         while (p < sin->s+sin->len) {
161                 if (*p == '%') {
162                         if (p[1] && p[2]) {
163                                 *at++ = pv_from_hex(p[1]) << 4 | pv_from_hex(p[2]);
164                                 p += 2;
165                         }
166                 } else if (*p == '+') {
167                         *at++ = ' ';
168                 } else {
169                         *at++ = *p;
170                 }
171                 p++;
172         }
173
174         *at = 0;
175         sout->len = at - sout->s;
176
177         LM_DBG("urldecoded string is <%s>\n", sout->s);
178         return 0;
179 }
180
181 /* Encode 7BIT PDU */
182 static int pdu_7bit_encode(str sin) {
183         int i, j;
184         unsigned char hex;
185         unsigned char nleft;
186         unsigned char fill;
187         char HexTbl[] = {"0123456789ABCDEF"};
188
189         nleft = 1;
190         j = 0;
191         for(i = 0; i < sin.len; i++) {
192                 hex = *(sin.s) >> (nleft - 1);
193                 fill = *(sin.s+1) << (8-nleft);
194                 hex = hex | fill;
195                 _tr_buffer[j++] = HexTbl[hex >> 4];
196                 _tr_buffer[j++] = HexTbl[hex & 0x0F];
197                 nleft++;
198                 if(nleft == 8) {
199                         sin.s++;
200                         i++;
201                         nleft = 1;
202                 }
203                 sin.s++;
204         }
205         _tr_buffer[j] = '\0';
206         return j;
207 }
208
209 /* Decode 7BIT PDU */
210 static int pdu_7bit_decode(str sin) {
211         int i, j;
212         unsigned char nleft = 1;
213         unsigned char fill = 0;
214         unsigned char oldfill = 0;
215         j = 0;
216         for(i = 0; i < sin.len; i += 2) {
217                 _tr_buffer[j] = (unsigned char)pv_from_hex(sin.s[i]) << 4;
218                 _tr_buffer[j] |= (unsigned char)pv_from_hex(sin.s[i+1]);
219                 fill = (unsigned char)_tr_buffer[j];
220                 fill >>= (8 - nleft);
221                 _tr_buffer[j] <<= (nleft -1 );
222                 _tr_buffer[j] &= 0x7F;
223                 _tr_buffer[j] |= oldfill;
224                 oldfill = fill;
225                 j++;
226                 nleft++;
227                 if(nleft == 8) {
228                         _tr_buffer[j++] = oldfill;
229                         nleft = 1;
230                         oldfill = 0;
231                 }
232         }
233         _tr_buffer[j] = '\0';
234         return j;
235 }
236
237 /* Get only the numeric part of string, e.g.
238  * 040/123-456 => 040123456 */
239 static int getNumericValue(str sin) {
240         int i, j = 0;
241         for(i = 0; i < sin.len; i ++) {
242                 if (sin.s[i] >= '0' && sin.s[i] <= '9') {
243                         _tr_buffer[j++] = sin.s[i];
244                 }
245         }
246         _tr_buffer[j] = '\0';
247         return j;
248 }
249
250 /* -- transformations functions */
251
252 /*!
253  * \brief Evaluate string transformations
254  * \param msg SIP message
255  * \param tp transformation
256  * \param subtype transformation type
257  * \param val pseudo-variable
258  * \return 0 on success, -1 on error
259  */
260 int tr_eval_string(struct sip_msg *msg, tr_param_t *tp, int subtype,
261                 pv_value_t *val)
262 {
263         int i, j, max;
264         char *p, *s;
265         str st, st2;
266         pv_value_t v, w;
267         time_t t;
268
269         if(val==NULL || val->flags&PV_VAL_NULL)
270                 return -1;
271
272         tr_set_crt_buffer();
273
274         switch(subtype)
275         {
276                 case TR_S_LEN:
277                         if(!(val->flags&PV_VAL_STR))
278                                 val->rs.s = int2str(val->ri, &val->rs.len);
279
280                         val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
281                         val->ri = val->rs.len;
282                         val->rs.s = int2str(val->ri, &val->rs.len);
283                         break;
284                 case TR_S_INT:
285                         if(!(val->flags&PV_VAL_INT))
286                         {
287                                 if(str2sint(&val->rs, &val->ri)!=0)
288                                         return -1;
289                         } else {
290                                 if(!(val->flags&PV_VAL_STR))
291                                         val->rs.s = int2str(val->ri, &val->rs.len);
292                         }
293
294                         val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
295                         break;
296                 case TR_S_MD5:
297                         if(!(val->flags&PV_VAL_STR))
298                                 val->rs.s = int2str(val->ri, &val->rs.len);
299
300                         compute_md5(_tr_buffer, val->rs.s, val->rs.len);
301                         _tr_buffer[MD5_LEN] = '\0';
302                         val->flags = PV_VAL_STR;
303                         val->ri = 0;
304                         val->rs.s = _tr_buffer;
305                         val->rs.len = MD5_LEN;
306                         break;
307                 case TR_S_SHA256:
308                         if(!(val->flags&PV_VAL_STR))
309                                 val->rs.s = int2str(val->ri, &val->rs.len);
310                         compute_sha256(_tr_buffer, (u_int8_t*)val->rs.s, val->rs.len);
311                         _tr_buffer[SHA256_DIGEST_STRING_LENGTH -1] = '\0';
312                         val->flags = PV_VAL_STR;
313                         val->ri = 0;
314                         val->rs.s = _tr_buffer;
315                         val->rs.len = SHA256_DIGEST_STRING_LENGTH -1 ;
316                         break;
317                 case TR_S_SHA384:
318                         if(!(val->flags&PV_VAL_STR))
319                                 val->rs.s = int2str(val->ri, &val->rs.len);
320                         compute_sha384(_tr_buffer, (u_int8_t*)val->rs.s, val->rs.len);
321                         _tr_buffer[SHA384_DIGEST_STRING_LENGTH -1] = '\0';
322                         val->flags = PV_VAL_STR;
323                         val->ri = 0;
324                         val->rs.s = _tr_buffer;
325                         val->rs.len = SHA384_DIGEST_STRING_LENGTH -1;
326                         break;
327                 case TR_S_SHA512:
328                         if(!(val->flags&PV_VAL_STR))
329                                 val->rs.s = int2str(val->ri, &val->rs.len);
330                         compute_sha512(_tr_buffer, (u_int8_t*)val->rs.s, val->rs.len);
331                         _tr_buffer[SHA512_DIGEST_STRING_LENGTH -1] = '\0';
332                         val->flags = PV_VAL_STR;
333                         val->ri = 0;
334                         val->rs.s = _tr_buffer;
335                         val->rs.len = SHA512_DIGEST_STRING_LENGTH -1;
336                         break;
337                 case TR_S_ENCODEHEXA:
338                         if(!(val->flags&PV_VAL_STR))
339                                 val->rs.s = int2str(val->ri, &val->rs.len);
340                         if(val->rs.len>TR_BUFFER_SIZE/2-1)
341                                 return -1;
342                         j = 0;
343                         for(i=0; i<val->rs.len; i++)
344                         {
345                                 _tr_buffer[j++] = fourbits2char[val->rs.s[i] >> 4];
346                                 _tr_buffer[j++] = fourbits2char[val->rs.s[i] & 0xf];
347                         }
348                         _tr_buffer[j] = '\0';
349                         memset(val, 0, sizeof(pv_value_t));
350                         val->flags = PV_VAL_STR;
351                         val->rs.s = _tr_buffer;
352                         val->rs.len = j;
353                         break;
354                 case TR_S_DECODEHEXA:
355                         if(!(val->flags&PV_VAL_STR))
356                                 val->rs.s = int2str(val->ri, &val->rs.len);
357                         if(val->rs.len>TR_BUFFER_SIZE*2-1)
358                                 return -1;
359                         for(i=0; i<val->rs.len/2; i++)
360                         {
361                                 if(val->rs.s[2*i]>='0'&&val->rs.s[2*i]<='9')
362                                         _tr_buffer[i] = (val->rs.s[2*i]-'0') << 4;
363                                 else if(val->rs.s[2*i]>='a'&&val->rs.s[2*i]<='f')
364                                         _tr_buffer[i] = (val->rs.s[2*i]-'a'+10) << 4;
365                                 else if(val->rs.s[2*i]>='A'&&val->rs.s[2*i]<='F')
366                                         _tr_buffer[i] = (val->rs.s[2*i]-'A'+10) << 4;
367                                 else return -1;
368
369                                 if(val->rs.s[2*i+1]>='0'&&val->rs.s[2*i+1]<='9')
370                                         _tr_buffer[i] += val->rs.s[2*i+1]-'0';
371                                 else if(val->rs.s[2*i+1]>='a'&&val->rs.s[2*i+1]<='f')
372                                         _tr_buffer[i] += val->rs.s[2*i+1]-'a'+10;
373                                 else if(val->rs.s[2*i+1]>='A'&&val->rs.s[2*i+1]<='F')
374                                         _tr_buffer[i] += val->rs.s[2*i+1]-'A'+10;
375                                 else return -1;
376                         }
377                         _tr_buffer[i] = '\0';
378                         memset(val, 0, sizeof(pv_value_t));
379                         val->flags = PV_VAL_STR;
380                         val->rs.s = _tr_buffer;
381                         val->rs.len = i;
382                         break;
383                 case TR_S_ENCODE7BIT:
384                         if(!(val->flags&PV_VAL_STR))
385                                 val->rs.s = int2str(val->ri, &val->rs.len);
386                         if(val->rs.len > (TR_BUFFER_SIZE*7/8) -1)
387                                 return -1;
388                         i = pdu_7bit_encode(val->rs);
389                         memset(val, 0, sizeof(pv_value_t));
390                         val->flags = PV_VAL_STR;
391                         val->rs.s = _tr_buffer;
392                         val->rs.len = i;
393                         break;
394                 case TR_S_DECODE7BIT:
395                         if(!(val->flags&PV_VAL_STR))
396                                 val->rs.s = int2str(val->ri, &val->rs.len);
397                         if(val->rs.len>TR_BUFFER_SIZE/2-1)
398                                 return -1;
399                         i = pdu_7bit_decode(val->rs);
400                         memset(val, 0, sizeof(pv_value_t));
401                         val->flags = PV_VAL_STR;
402                         val->rs.s = _tr_buffer;
403                         val->rs.len = i;
404                         break;
405                 case TR_S_NUMERIC:
406                         if(!(val->flags&PV_VAL_STR))
407                                 return -1;
408                         if(val->rs.len>TR_BUFFER_SIZE)
409                                 return -1;
410                         i = getNumericValue(val->rs);
411                         memset(val, 0, sizeof(pv_value_t));
412                         val->flags = PV_VAL_STR;
413                         val->rs.s = _tr_buffer;
414                         val->rs.len = i;
415                         break;
416                 case TR_S_ENCODEBASE58:
417                         if(!(val->flags&PV_VAL_STR))
418                                 val->rs.s = int2str(val->ri, &val->rs.len);
419                         st.len = TR_BUFFER_SIZE-1;
420                         st.s = b58_encode(_tr_buffer, &st.len, val->rs.s, val->rs.len);
421                         if (st.s==NULL)
422                                 return -1;
423                         memset(val, 0, sizeof(pv_value_t));
424                         val->flags = PV_VAL_STR;
425                         val->rs.s = st.s;
426                         val->rs.len = st.len;
427                         break;
428                 case TR_S_DECODEBASE58:
429                         if(!(val->flags&PV_VAL_STR))
430                                 val->rs.s = int2str(val->ri, &val->rs.len);
431                         st.len = TR_BUFFER_SIZE-1;
432                         st.s = b58_decode(_tr_buffer, &st.len, val->rs.s, val->rs.len);
433                         if (st.s==NULL)
434                                 return -1;
435                         memset(val, 0, sizeof(pv_value_t));
436                         val->flags = PV_VAL_STR;
437                         val->rs.s = st.s;
438                         val->rs.len = st.len;
439                         break;
440                 case TR_S_ENCODEBASE64:
441                         if(!(val->flags&PV_VAL_STR))
442                                 val->rs.s = int2str(val->ri, &val->rs.len);
443                         i = base64_enc((unsigned char *) val->rs.s, val->rs.len,
444                                         (unsigned char *) _tr_buffer, TR_BUFFER_SIZE-1);
445                         if (i < 0)
446                                 return -1;
447                         _tr_buffer[i] = '\0';
448                         memset(val, 0, sizeof(pv_value_t));
449                         val->flags = PV_VAL_STR;
450                         val->rs.s = _tr_buffer;
451                         val->rs.len = i;
452                         break;
453                 case TR_S_DECODEBASE64:
454                         if(!(val->flags&PV_VAL_STR))
455                                 val->rs.s = int2str(val->ri, &val->rs.len);
456                         i = base64_dec((unsigned char *) val->rs.s, val->rs.len,
457                                         (unsigned char *) _tr_buffer, TR_BUFFER_SIZE-1);
458                         if (i < 0 || (i == 0 && val->rs.len > 0))
459                                 return -1;
460                         _tr_buffer[i] = '\0';
461                         memset(val, 0, sizeof(pv_value_t));
462                         val->flags = PV_VAL_STR;
463                         val->rs.s = _tr_buffer;
464                         val->rs.len = i;
465                         break;
466                 case TR_S_ESCAPECOMMON:
467                         if(!(val->flags&PV_VAL_STR))
468                                 val->rs.s = int2str(val->ri, &val->rs.len);
469                         if(val->rs.len>TR_BUFFER_SIZE/2-1)
470                                 return -1;
471                         i = escape_common(_tr_buffer, val->rs.s, val->rs.len);
472                         _tr_buffer[i] = '\0';
473                         memset(val, 0, sizeof(pv_value_t));
474                         val->flags = PV_VAL_STR;
475                         val->rs.s = _tr_buffer;
476                         val->rs.len = i;
477                         break;
478                 case TR_S_UNESCAPECOMMON:
479                         if(!(val->flags&PV_VAL_STR))
480                                 val->rs.s = int2str(val->ri, &val->rs.len);
481                         if(val->rs.len>TR_BUFFER_SIZE-1)
482                                 return -1;
483                         i = unescape_common(_tr_buffer, val->rs.s, val->rs.len);
484                         _tr_buffer[i] = '\0';
485                         memset(val, 0, sizeof(pv_value_t));
486                         val->flags = PV_VAL_STR;
487                         val->rs.s = _tr_buffer;
488                         val->rs.len = i;
489                         break;
490                 case TR_S_ESCAPEUSER:
491                         if(!(val->flags&PV_VAL_STR))
492                                 val->rs.s = int2str(val->ri, &val->rs.len);
493                         if(val->rs.len>TR_BUFFER_SIZE/2-1)
494                                 return -1;
495                         st.s = _tr_buffer;
496                         st.len = TR_BUFFER_SIZE;
497                         if (escape_user(&val->rs, &st))
498                                 return -1;
499                         memset(val, 0, sizeof(pv_value_t));
500                         val->flags = PV_VAL_STR;
501                         val->rs = st;
502                         break;
503                 case TR_S_UNESCAPEUSER:
504                         if(!(val->flags&PV_VAL_STR))
505                                 val->rs.s = int2str(val->ri, &val->rs.len);
506                         if(val->rs.len>TR_BUFFER_SIZE-1)
507                                 return -1;
508                         st.s = _tr_buffer;
509                         st.len = TR_BUFFER_SIZE;
510                         if (unescape_user(&val->rs, &st))
511                                 return -1;
512                         memset(val, 0, sizeof(pv_value_t));
513                         val->flags = PV_VAL_STR;
514                         val->rs = st;
515                         break;
516                 case TR_S_ESCAPEPARAM:
517                         if(!(val->flags&PV_VAL_STR))
518                                 val->rs.s = int2str(val->ri, &val->rs.len);
519                         if(val->rs.len>TR_BUFFER_SIZE/2-1)
520                                 return -1;
521                         st.s = _tr_buffer;
522                         st.len = TR_BUFFER_SIZE;
523                         if (escape_param(&val->rs, &st) < 0)
524                                 return -1;
525                         memset(val, 0, sizeof(pv_value_t));
526                         val->flags = PV_VAL_STR;
527                         val->rs = st;
528                         break;
529                 case TR_S_UNESCAPEPARAM:
530                         if(!(val->flags&PV_VAL_STR))
531                                 val->rs.s = int2str(val->ri, &val->rs.len);
532                         if(val->rs.len>TR_BUFFER_SIZE-1)
533                                 return -1;
534                         st.s = _tr_buffer;
535                         st.len = TR_BUFFER_SIZE;
536                         if (unescape_param(&val->rs, &st) < 0)
537                                 return -1;
538                         memset(val, 0, sizeof(pv_value_t));
539                         val->flags = PV_VAL_STR;
540                         val->rs = st;
541                         break;
542                 case TR_S_ESCAPECSV:
543                         if(!(val->flags&PV_VAL_STR))
544                                 val->rs.s = int2str(val->ri, &val->rs.len);
545                         st.s = _tr_buffer;
546                         st.len = TR_BUFFER_SIZE;
547                         if (escape_csv(&val->rs, &st))
548                                 return -1;
549                         memset(val, 0, sizeof(pv_value_t));
550                         val->flags = PV_VAL_STR;
551                         val->rs = st;
552                         break;
553                 case TR_S_SUBSTR:
554                         if(tp==NULL || tp->next==NULL)
555                         {
556                                 LM_ERR("substr invalid parameters (cfg line: %d)\n",
557                                                 get_cfg_crt_line());
558                                 return -1;
559                         }
560                         if(!(val->flags&PV_VAL_STR))
561                                 val->rs.s = int2str(val->ri, &val->rs.len);
562                         if(tp->type==TR_PARAM_NUMBER)
563                         {
564                                 i = tp->v.n;
565                         } else {
566                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
567                                                 || (!(v.flags&PV_VAL_INT)))
568                                 {
569                                         LM_ERR("substr cannot get p1 (cfg line: %d)\n",
570                                                         get_cfg_crt_line());
571                                         return -1;
572                                 }
573                                 i = v.ri;
574                         }
575                         if(tp->next->type==TR_PARAM_NUMBER)
576                         {
577                                 j = tp->next->v.n;
578                         } else {
579                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->next->v.data, &v)!=0
580                                                 || (!(v.flags&PV_VAL_INT)))
581                                 {
582                                         LM_ERR("substr cannot get p2 (cfg line: %d)\n",
583                                                         get_cfg_crt_line());
584                                         return -1;
585                                 }
586                                 j = v.ri;
587                         }
588                         LM_DBG("i=%d j=%d\n", i, j);
589                         if(j<0)
590                         {
591                                 LM_ERR("substr negative offset (cfg line: %d)\n",
592                                                 get_cfg_crt_line());
593                                 return -1;
594                         }
595                         val->flags = PV_VAL_STR;
596                         val->ri = 0;
597                         if(i>=0)
598                         {
599                                 if(i>=val->rs.len)
600                                 {
601                                         LM_ERR("substr out of range (cfg line: %d)\n",
602                                                         get_cfg_crt_line());
603                                         return -1;
604                                 }
605                                 if(i+j>=val->rs.len) j=0;
606                                 if(j==0)
607                                 { /* to end */
608                                         val->rs.s += i;
609                                         val->rs.len -= i;
610                                         tr_string_clone_result;
611                                         break;
612                                 }
613                                 val->rs.s += i;
614                                 val->rs.len = j;
615                                 break;
616                         }
617                         i = -i;
618                         if(i>val->rs.len)
619                         {
620                                 LM_ERR("substr out of range (cfg line: %d)\n",
621                                                 get_cfg_crt_line());
622                                 return -1;
623                         }
624                         if(i<j) j=0;
625                         if(j==0)
626                         { /* to end */
627                                 val->rs.s += val->rs.len-i;
628                                 val->rs.len = i;
629                                 tr_string_clone_result;
630                                 break;
631                         }
632                         val->rs.s += val->rs.len-i;
633                         val->rs.len = j;
634                         tr_string_clone_result;
635                         break;
636
637                 case TR_S_SELECT:
638                         if(tp==NULL || tp->next==NULL)
639                         {
640                                 LM_ERR("select invalid parameters (cfg line: %d)\n",
641                                                 get_cfg_crt_line());
642                                 return -1;
643                         }
644                         if(!(val->flags&PV_VAL_STR))
645                                 val->rs.s = int2str(val->ri, &val->rs.len);
646                         if(tp->type==TR_PARAM_NUMBER)
647                         {
648                                 i = tp->v.n;
649                         } else {
650                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
651                                                 || (!(v.flags&PV_VAL_INT)))
652                                 {
653                                         LM_ERR("select cannot get p1 (cfg line: %d)\n",
654                                                         get_cfg_crt_line());
655                                         return -1;
656                                 }
657                                 i = v.ri;
658                         }
659                         val->flags = PV_VAL_STR;
660                         val->ri = 0;
661                         if(i<0)
662                         {
663                                 s = val->rs.s+val->rs.len-1;
664                                 p = s;
665                                 i = -i;
666                                 i--;
667                                 while(p>=val->rs.s)
668                                 {
669                                         if(*p==tp->next->v.s.s[0])
670                                         {
671                                                 if(i==0)
672                                                         break;
673                                                 s = p-1;
674                                                 i--;
675                                         }
676                                         p--;
677                                 }
678                                 if(i==0)
679                                 {
680                                         val->rs.s = p+1;
681                                         val->rs.len = s-p;
682                                 } else {
683                                         val->rs = _tr_empty;
684                                 }
685                         } else {
686                                 s = val->rs.s;
687                                 p = s;
688                                 while(p<val->rs.s+val->rs.len)
689                                 {
690                                         if(*p==tp->next->v.s.s[0])
691                                         {
692                                                 if(i==0)
693                                                         break;
694                                                 s = p + 1;
695                                                 i--;
696                                         }
697                                         p++;
698                                 }
699                                 if(i==0)
700                                 {
701                                         val->rs.s = s;
702                                         val->rs.len = p-s;
703                                 } else {
704                                         val->rs = _tr_empty;
705                                 }
706                         }
707                         tr_string_clone_result;
708                         break;
709
710                 case TR_S_TOLOWER:
711                         if(!(val->flags&PV_VAL_STR))
712                         {
713                                 val->rs.s = int2str(val->ri, &val->rs.len);
714                                 val->flags |= PV_VAL_STR;
715                                 break;
716                         }
717                         if(val->rs.len>TR_BUFFER_SIZE-1)
718                                 return -1;
719                         st.s = _tr_buffer;
720                         st.len = val->rs.len;
721                         for (i=0; i<st.len; i++)
722                                 st.s[i]=(val->rs.s[i]>='A' && val->rs.s[i]<='Z')
723                                         ?('a' + val->rs.s[i] -'A'):val->rs.s[i];
724                         memset(val, 0, sizeof(pv_value_t));
725                         val->flags = PV_VAL_STR;
726                         val->rs = st;
727                         break;
728
729                 case TR_S_TOUPPER:
730                         if(!(val->flags&PV_VAL_STR))
731                         {
732                                 val->rs.s = int2str(val->ri, &val->rs.len);
733                                 val->flags |= PV_VAL_STR;
734                                 break;
735                         }
736                         if(val->rs.len>TR_BUFFER_SIZE-1)
737                                 return -1;
738                         st.s = _tr_buffer;
739                         st.len = val->rs.len;
740                         for (i=0; i<st.len; i++)
741                                 st.s[i]=(val->rs.s[i]>='a' && val->rs.s[i]<='z')
742                                         ?('A' + val->rs.s[i] -'a'):val->rs.s[i];
743                         memset(val, 0, sizeof(pv_value_t));
744                         val->flags = PV_VAL_STR;
745                         val->rs = st;
746                         break;
747
748                 case TR_S_STRIP:
749                 case TR_S_STRIPTAIL:
750                         if(tp==NULL)
751                         {
752                                 LM_ERR("strip invalid parameters (cfg line: %d)\n",
753                                                 get_cfg_crt_line());
754                                 return -1;
755                         }
756                         if(!(val->flags&PV_VAL_STR))
757                                 val->rs.s = int2str(val->ri, &val->rs.len);
758                         if(tp->type==TR_PARAM_NUMBER)
759                         {
760                                 i = tp->v.n;
761                         } else {
762                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
763                                                 || (!(v.flags&PV_VAL_INT)))
764                                 {
765                                         LM_ERR("select cannot get p1 (cfg line: %d)\n",
766                                                         get_cfg_crt_line());
767                                         return -1;
768                                 }
769                                 i = v.ri;
770                         }
771                         val->flags = PV_VAL_STR;
772                         val->ri = 0;
773                         if(i<=0)
774                                 break;
775                         if(i>=val->rs.len)
776                         {
777                                 _tr_buffer[0] = '\0';
778                                 val->rs.s = _tr_buffer;
779                                 val->rs.len = 0;
780                                 break;
781                         }
782                         if(subtype==TR_S_STRIP)
783                                 val->rs.s += i;
784                         val->rs.len -= i;
785                         tr_string_clone_result;
786                         break;
787
788
789                 case TR_S_STRIPTO:
790                         if(tp==NULL)
791                         {
792                                 LM_ERR("stripto invalid parameters (cfg line: %d)\n",
793                                                 get_cfg_crt_line());
794                                 return -1;
795                         }
796                         if(!(val->flags&PV_VAL_STR))
797                                 val->rs.s = int2str(val->ri, &val->rs.len);
798
799                         if(tp->type==TR_PARAM_STRING)
800                         {
801                                 st = tp->v.s;
802                         } else {
803                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
804                                                 || (!(v.flags&PV_VAL_STR)) || v.rs.len<=0)
805                                 {
806                                         LM_ERR("stripto cannot get p1 (cfg line: %d)\n",
807                                                         get_cfg_crt_line());
808                                         return -1;
809                                 }
810                                 st = v.rs;
811                         }
812
813                         val->flags = PV_VAL_STR;
814                         val->ri = 0;
815                         for(i=0; i<val->rs.len; i++)
816                         {
817                                 if(val->rs.s[i] == st.s[0])
818                                         break;
819                         }
820                         if(i>=val->rs.len)
821                         {
822                                 _tr_buffer[0] = '\0';
823                                 val->rs.s = _tr_buffer;
824                                 val->rs.len = 0;
825                                 break;
826                         }
827                         val->rs.s += i;
828                         val->rs.len -= i;
829                         tr_string_clone_result;
830                         break;
831
832                 case TR_S_PREFIXES:
833                 case TR_S_PREFIXES_QUOT:
834                         if(!(val->flags&PV_VAL_STR))
835                                 val->rs.s = int2str(val->ri, &val->rs.len);
836
837                         /* Set maximum prefix length */
838                         max = val->rs.len;
839                         if(tp!=NULL) {
840                                 if(tp->type==TR_PARAM_NUMBER) {
841                                         if (tp->v.n > 0 && tp->v.n < max)
842                                                 max = tp->v.n;
843                                 } else {
844                                         if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
845                                                         || (!(v.flags&PV_VAL_INT)))
846                                         {
847                                                 LM_ERR("prefixes cannot get max (cfg line: %d)\n",
848                                                                 get_cfg_crt_line());
849                                                 return -1;
850                                         }
851                                         if (v.ri > 0 && v.ri < max)
852                                                 max  = v.ri;
853                                 }
854                         }
855
856                         if(max * (max/2 + (subtype==TR_S_PREFIXES_QUOT ? 1 : 3)) > TR_BUFFER_SIZE-1) {
857                                 LM_ERR("prefixes buffer too short (cfg line: %d)\n",
858                                                 get_cfg_crt_line());
859                                 return -1;
860                         }
861
862                         j = 0;
863                         for (i=1; i <= max; i++) {
864                                 if (subtype==TR_S_PREFIXES_QUOT)
865                                         _tr_buffer[j++] = '\'';
866                                 memcpy(&(_tr_buffer[j]), val->rs.s, i);
867                                 j += i;
868                                 if (subtype==TR_S_PREFIXES_QUOT)
869                                         _tr_buffer[j++] = '\'';
870                                 _tr_buffer[j++] = ',';
871                         }
872                         memset(val, 0, sizeof(pv_value_t));
873                         val->flags = PV_VAL_STR;
874                         val->rs.s = _tr_buffer;
875                         val->rs.len = j-1;
876                         break;
877
878
879                 case TR_S_REPLACE:
880                         if(tp==NULL || tp->next==NULL)
881                         {
882                                 LM_ERR("select invalid parameters (cfg line: %d)\n",
883                                                 get_cfg_crt_line());
884                                 return -1;
885                         }
886                         if(!(val->flags&PV_VAL_STR))
887                                 val->rs.s = int2str(val->ri, &val->rs.len);
888
889                         if(tp->type==TR_PARAM_STRING)
890                         {
891                                 st = tp->v.s;
892                         } else {
893                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
894                                                 || (!(v.flags&PV_VAL_STR)) || v.rs.len<=0)
895                                 {
896                                         LM_ERR("replace cannot get p1 (cfg line: %d)\n",
897                                                         get_cfg_crt_line());
898                                         return -1;
899                                 }
900                                 st = v.rs;
901                         }
902
903                         if(tp->next->type==TR_PARAM_STRING)
904                         {
905                                 st2 = tp->next->v.s;
906                         } else {
907                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->next->v.data, &w)!=0
908                                                 || (!(w.flags&PV_VAL_STR)) || w.rs.len<=0)
909                                 {
910                                         LM_ERR("replace cannot get p2 (cfg line: %d)\n",
911                                                         get_cfg_crt_line());
912                                         return -1;
913                                 }
914                                 st2 = w.rs;
915                         }
916
917                         val->flags = PV_VAL_STR;
918                         val->ri = 0;
919
920                         i = 0;
921                         j = 0;
922                         max = val->rs.len - st.len;
923                         while (i < val->rs.len && j < TR_BUFFER_SIZE) {
924                                 if (i <= max && val->rs.s[i] == st.s[0]
925                                                 && strncmp(val->rs.s+i, st.s, st.len) == 0) {
926                                         strncpy(_tr_buffer+j, st2.s, st2.len);
927                                         i += st.len;
928                                         j += st2.len;
929                                 } else {
930                                         _tr_buffer[j++] = val->rs.s[i++];
931                                 }
932                         }
933                         val->rs.s = _tr_buffer;
934                         val->rs.len = j;
935                         break;
936
937                 case TR_S_TIMEFORMAT:
938                         if(tp==NULL)
939                         {
940                                 LM_ERR("timeformat invalid parameters (cfg line: %d)\n",
941                                                 get_cfg_crt_line());
942                                 return -1;
943                         }
944                         if(!(val->flags&PV_VAL_INT) && (str2int(&val->rs,
945                                                         (unsigned int*) &val->ri)!=0))
946                         {
947                                 LM_ERR("value is not numeric (cfg line: %d)\n",
948                                                 get_cfg_crt_line());
949                                 return -1;
950                         }
951                         if(tp->type==TR_PARAM_STRING)
952                         {
953                                 st = tp->v.s;
954                         } else {
955                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
956                                                 || (!(v.flags&PV_VAL_STR)) || v.rs.len<=0)
957                                 {
958                                         LM_ERR("timeformat cannot get p1 (cfg line: %d)\n",
959                                                         get_cfg_crt_line());
960                                         return -1;
961                                 }
962                                 st = v.rs;
963                         }
964                         s = pkg_malloc(st.len + 1);
965                         if (s==NULL)
966                         {
967                                 LM_ERR("no more pkg memory (cfg line: %d)\n",
968                                                 get_cfg_crt_line());
969                                 return -1;
970                         }
971                         memcpy(s, st.s, st.len);
972                         s[st.len] = '\0';
973                         t = val->ri;
974                         val->rs.len = strftime(_tr_buffer, TR_BUFFER_SIZE-1, s,
975                                         localtime(&t));
976                         pkg_free(s);
977                         val->flags = PV_VAL_STR;
978                         val->rs.s = _tr_buffer;
979                         break;
980
981                 case TR_S_TRIM:
982                         if(!(val->flags&PV_VAL_STR))
983                                 val->rs.s = int2str(val->ri, &val->rs.len);
984                         if(val->rs.len>TR_BUFFER_SIZE-2)
985                                 return -1;
986                         memcpy(_tr_buffer, val->rs.s, val->rs.len);
987                         val->flags = PV_VAL_STR;
988                         val->rs.s = _tr_buffer;
989                         trim(&val->rs);
990                         val->rs.s[val->rs.len] = '\0';
991                         break;
992
993                 case TR_S_RTRIM:
994                         if(!(val->flags&PV_VAL_STR))
995                                 val->rs.s = int2str(val->ri, &val->rs.len);
996                         if(val->rs.len>TR_BUFFER_SIZE-2)
997                                 return -1;
998                         memcpy(_tr_buffer, val->rs.s, val->rs.len);
999                         val->flags = PV_VAL_STR;
1000                         val->rs.s = _tr_buffer;
1001                         trim_trailing(&val->rs);
1002                         val->rs.s[val->rs.len] = '\0';
1003                         break;
1004
1005                 case TR_S_LTRIM:
1006                         if(!(val->flags&PV_VAL_STR))
1007                                 val->rs.s = int2str(val->ri, &val->rs.len);
1008                         if(val->rs.len>TR_BUFFER_SIZE-2)
1009                                 return -1;
1010                         memcpy(_tr_buffer, val->rs.s, val->rs.len);
1011                         val->flags = PV_VAL_STR;
1012                         val->rs.s = _tr_buffer;
1013                         trim_leading(&val->rs);
1014                         val->rs.s[val->rs.len] = '\0';
1015                         break;
1016
1017                 case TR_S_RM:
1018                         if(tp==NULL)
1019                         {
1020                                 LM_ERR("invalid parameters (cfg line: %d)\n",
1021                                                 get_cfg_crt_line());
1022                                 return -1;
1023                         }
1024                         if(!(val->flags&PV_VAL_STR))
1025                                 val->rs.s = int2str(val->ri, &val->rs.len);
1026                         if(val->rs.len>TR_BUFFER_SIZE-2)
1027                                 return -1;
1028                         if(tp->type==TR_PARAM_STRING)
1029                         {
1030                                 st = tp->v.s;
1031                                 if(memchr(st.s, '\\', st.len)) {
1032                                         p = pv_get_buffer();
1033                                         if(st.len>=pv_get_buffer_size()-1)
1034                                                 return -1;
1035                                         j=0;
1036                                         for(i=0; i<st.len-1; i++) {
1037                                                 if(st.s[i]=='\\') {
1038                                                         switch(st.s[i+1]) {
1039                                                                 case 'n':
1040                                                                         p[j++] = '\n';
1041                                                                         break;
1042                                                                 case 'r':
1043                                                                         p[j++] = '\r';
1044                                                                         break;
1045                                                                 case 't':
1046                                                                         p[j++] = '\t';
1047                                                                         break;
1048                                                                 case '\\':
1049                                                                         p[j++] = '\\';
1050                                                                         break;
1051                                                                 default:
1052                                                                         p[j++] = st.s[i+1];
1053                                                         }
1054                                                         i++;
1055                                                 } else {
1056                                                         p[j++] = st.s[i];
1057                                                 }
1058                                         }
1059                                         if(i==st.len-1)
1060                                                 p[j++] = st.s[i];
1061                                         p[j] = '\0';
1062                                         st.s = p;
1063                                         st.len = j;
1064                                 }
1065                         } else {
1066                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
1067                                                 || (!(v.flags&PV_VAL_STR)) || v.rs.len<=0)
1068                                 {
1069                                         LM_ERR("cannot get parameter value (cfg line: %d)\n",
1070                                                         get_cfg_crt_line());
1071                                         return -1;
1072                                 }
1073                                 st = v.rs;
1074                         }
1075                         LM_DBG("removing [%.*s](%d) in [%.*s](%d)\n",
1076                                         st.len, st.s, st.len, val->rs.len, val->rs.s, val->rs.len);
1077                         val->flags = PV_VAL_STR;
1078                         val->ri = 0;
1079
1080                         i = 0;
1081                         j = 0;
1082                         max = val->rs.len - st.len;
1083                         while (i < val->rs.len && j < TR_BUFFER_SIZE) {
1084                                 if (i <= max && val->rs.s[i] == st.s[0]
1085                                                 && strncmp(val->rs.s+i, st.s, st.len) == 0) {
1086                                         i += st.len;
1087                                 } else {
1088                                         _tr_buffer[j++] = val->rs.s[i++];
1089                                 }
1090                         }
1091                         val->rs.s = _tr_buffer;
1092                         val->rs.s[j] = '\0';
1093                         val->rs.len = j;
1094                         break;
1095
1096                 case TR_S_URLENCODEPARAM:
1097                         if(!(val->flags&PV_VAL_STR))
1098                                 val->rs.s = int2str(val->ri, &val->rs.len);
1099                         if(val->rs.len>TR_BUFFER_SIZE-1)
1100                                 return -1;
1101                         st.s = _tr_buffer;
1102                         st.len = TR_BUFFER_SIZE;
1103                         if (urlencode_param(&val->rs, &st) < 0)
1104                                 return -1;
1105                         memset(val, 0, sizeof(pv_value_t));
1106                         val->flags = PV_VAL_STR;
1107                         val->rs = st;
1108                         break;
1109
1110                 case TR_S_URLDECODEPARAM:
1111                         if(!(val->flags&PV_VAL_STR))
1112                                 val->rs.s = int2str(val->ri, &val->rs.len);
1113                         if(val->rs.len>TR_BUFFER_SIZE-1)
1114                                 return -1;
1115                         st.s = _tr_buffer;
1116                         st.len = TR_BUFFER_SIZE;
1117                         if (urldecode_param(&val->rs, &st) < 0)
1118                                 return -1;
1119                         memset(val, 0, sizeof(pv_value_t));
1120                         val->flags = PV_VAL_STR;
1121                         val->rs = st;
1122                         break;
1123
1124                 default:
1125                         LM_ERR("unknown subtype %d (cfg line: %d)\n",
1126                                         subtype, get_cfg_crt_line());
1127                         return -1;
1128         }
1129         return 0;
1130 }
1131
1132
1133 /*!
1134  * \brief Evaluate URI transformations
1135  * \param msg SIP message
1136  * \param tp transformation
1137  * \param subtype transformation type
1138  * \param val pseudo-variable
1139  * \return 0 on success, -1 on error
1140  */
1141 int tr_eval_uri(struct sip_msg *msg, tr_param_t *tp, int subtype,
1142                 pv_value_t *val)
1143 {
1144         pv_value_t v;
1145         str sv;
1146         param_hooks_t phooks;
1147         param_t *pit=NULL;
1148
1149         if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
1150                 return -1;
1151
1152         if(_tr_uri.len==0 || _tr_uri.len!=val->rs.len ||
1153                         strncmp(_tr_uri.s, val->rs.s, val->rs.len)!=0)
1154         {
1155                 if(val->rs.len>_tr_uri.len)
1156                 {
1157                         if(_tr_uri.s) pkg_free(_tr_uri.s);
1158                         _tr_uri.s = (char*)pkg_malloc((val->rs.len+1)*sizeof(char));
1159                         if(_tr_uri.s==NULL)
1160                         {
1161                                 LM_ERR("no more private memory\n");
1162                                 if(_tr_uri_params != NULL)
1163                                 {
1164                                         free_params(_tr_uri_params);
1165                                         _tr_uri_params = 0;
1166                                 }
1167                                 memset(&_tr_uri, 0, sizeof(str));
1168                                 memset(&_tr_parsed_uri, 0, sizeof(struct sip_uri));
1169                                 return -1;
1170                         }
1171                 }
1172                 _tr_uri.len = val->rs.len;
1173                 memcpy(_tr_uri.s, val->rs.s, val->rs.len);
1174                 _tr_uri.s[_tr_uri.len] = '\0';
1175                 /* reset old values */
1176                 memset(&_tr_parsed_uri, 0, sizeof(struct sip_uri));
1177                 if(_tr_uri_params != NULL)
1178                 {
1179                         free_params(_tr_uri_params);
1180                         _tr_uri_params = 0;
1181                 }
1182                 /* parse uri -- params only when requested */
1183                 if(parse_uri(_tr_uri.s, _tr_uri.len, &_tr_parsed_uri)!=0)
1184                 {
1185                         LM_ERR("invalid uri [%.*s]\n", val->rs.len,
1186                                         val->rs.s);
1187                         if(_tr_uri_params != NULL)
1188                         {
1189                                 free_params(_tr_uri_params);
1190                                 _tr_uri_params = 0;
1191                         }
1192                         pkg_free(_tr_uri.s);
1193                         memset(&_tr_uri, 0, sizeof(str));
1194                         memset(&_tr_parsed_uri, 0, sizeof(struct sip_uri));
1195                         return -1;
1196                 }
1197         }
1198         memset(val, 0, sizeof(pv_value_t));
1199         val->flags = PV_VAL_STR;
1200
1201         switch(subtype)
1202         {
1203                 case TR_URI_USER:
1204                         val->rs = (_tr_parsed_uri.user.s)?_tr_parsed_uri.user:_tr_empty;
1205                         break;
1206                 case TR_URI_HOST:
1207                         val->rs = (_tr_parsed_uri.host.s)?_tr_parsed_uri.host:_tr_empty;
1208                         break;
1209                 case TR_URI_PASSWD:
1210                         val->rs = (_tr_parsed_uri.passwd.s)?_tr_parsed_uri.passwd:_tr_empty;
1211                         break;
1212                 case TR_URI_PORT:
1213                         val->flags |= PV_TYPE_INT|PV_VAL_INT;
1214                         val->rs = (_tr_parsed_uri.port.s)?_tr_parsed_uri.port:_tr_empty;
1215                         val->ri = _tr_parsed_uri.port_no;
1216                         break;
1217                 case TR_URI_PARAMS:
1218                         val->rs = (_tr_parsed_uri.sip_params.s)?_tr_parsed_uri.sip_params:_tr_empty;
1219                         break;
1220                 case TR_URI_PARAM:
1221                         if(tp==NULL)
1222                         {
1223                                 LM_ERR("param invalid parameters\n");
1224                                 return -1;
1225                         }
1226                         if(_tr_parsed_uri.sip_params.len<=0)
1227                         {
1228                                 val->rs = _tr_empty;
1229                                 val->flags = PV_VAL_STR;
1230                                 val->ri = 0;
1231                                 break;
1232                         }
1233
1234                         if(_tr_uri_params == NULL)
1235                         {
1236                                 sv = _tr_parsed_uri.sip_params;
1237                                 if (parse_params(&sv, CLASS_ANY, &phooks, &_tr_uri_params)<0)
1238                                         return -1;
1239                         }
1240                         if(tp->type==TR_PARAM_STRING)
1241                         {
1242                                 sv = tp->v.s;
1243                         } else {
1244                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
1245                                                 || (!(v.flags&PV_VAL_STR)) || v.rs.len<=0)
1246                                 {
1247                                         LM_ERR("param cannot get p1\n");
1248                                         return -1;
1249                                 }
1250                                 sv = v.rs;
1251                         }
1252                         for (pit = _tr_uri_params; pit; pit=pit->next)
1253                         {
1254                                 if (pit->name.len==sv.len
1255                                                 && strncasecmp(pit->name.s, sv.s, sv.len)==0)
1256                                 {
1257                                         val->rs = pit->body;
1258                                         goto done;
1259                                 }
1260                         }
1261                         val->rs = _tr_empty;
1262                         break;
1263                 case TR_URI_HEADERS:
1264                         val->rs = (_tr_parsed_uri.headers.s)?_tr_parsed_uri.headers:
1265                                 _tr_empty;
1266                         break;
1267                 case TR_URI_TRANSPORT:
1268                         val->rs = (_tr_parsed_uri.transport_val.s)?
1269                                 _tr_parsed_uri.transport_val:_tr_empty;
1270                         break;
1271                 case TR_URI_TTL:
1272                         val->rs = (_tr_parsed_uri.ttl_val.s)?
1273                                 _tr_parsed_uri.ttl_val:_tr_empty;
1274                         break;
1275                 case TR_URI_UPARAM:
1276                         val->rs = (_tr_parsed_uri.user_param_val.s)?
1277                                 _tr_parsed_uri.user_param_val:_tr_empty;
1278                         break;
1279                 case TR_URI_MADDR:
1280                         val->rs = (_tr_parsed_uri.maddr_val.s)?
1281                                 _tr_parsed_uri.maddr_val:_tr_empty;
1282                         break;
1283                 case TR_URI_METHOD:
1284                         val->rs = (_tr_parsed_uri.method_val.s)?
1285                                 _tr_parsed_uri.method_val:_tr_empty;
1286                         break;
1287                 case TR_URI_LR:
1288                         val->rs = (_tr_parsed_uri.lr_val.s)?
1289                                 _tr_parsed_uri.lr_val:_tr_empty;
1290                         break;
1291                 case TR_URI_R2:
1292                         val->rs = (_tr_parsed_uri.r2_val.s)?
1293                                 _tr_parsed_uri.r2_val:_tr_empty;
1294                         break;
1295                 default:
1296                         LM_ERR("unknown subtype %d\n",
1297                                         subtype);
1298                         return -1;
1299         }
1300 done:
1301         return 0;
1302 }
1303
1304 static str _tr_params_str = {0, 0};
1305 static param_t* _tr_params_list = NULL;
1306 static char _tr_params_separator = ';';
1307
1308
1309 /*!
1310  * \brief Evaluate parameter transformations
1311  * \param msg SIP message
1312  * \param tp transformation
1313  * \param subtype transformation type
1314  * \param val pseudo-variable
1315  * \return 0 on success, -1 on error
1316  */
1317 int tr_eval_paramlist(struct sip_msg *msg, tr_param_t *tp, int subtype,
1318                 pv_value_t *val)
1319 {
1320         pv_value_t v;
1321         pv_value_t vs;
1322         str sv;
1323         int n, i;
1324         char separator = ';';
1325         param_hooks_t phooks;
1326         param_t *pit=NULL;
1327
1328         if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
1329                 return -1;
1330
1331         if (tp != NULL)
1332         {
1333                 if (subtype == TR_PL_COUNT)
1334                 {
1335                         if(tp->type != TR_PARAM_STRING) {
1336                                 if(pv_get_spec_value(msg, (pv_spec_t*)tp->v.data, &vs)!=0
1337                                                 || (!(vs.flags&PV_VAL_STR)) || vs.rs.len<=0)
1338                                 {
1339                                         LM_ERR("value cannot get p1\n");
1340                                         return -1;
1341                                 }
1342                                 separator = vs.rs.s[0];
1343                         } else {
1344                                 if(tp->v.s.len != 1)
1345                                         return -1;
1346                                 separator = tp->v.s.s[0];
1347                         }
1348                 } else if (tp->next != NULL) {
1349                         if(tp->next->type != TR_PARAM_STRING
1350                                         || tp->next->v.s.len != 1)
1351                                 return -1;
1352                         separator = tp->next->v.s.s[0];
1353                 }
1354         }
1355
1356         if(_tr_params_str.len==0 || _tr_params_str.len!=val->rs.len ||
1357                         strncmp(_tr_params_str.s, val->rs.s, val->rs.len)!=0 ||
1358                         _tr_params_separator != separator)
1359         {
1360                 _tr_params_separator = separator;
1361
1362                 if(val->rs.len>_tr_params_str.len)
1363                 {
1364                         if(_tr_params_str.s) pkg_free(_tr_params_str.s);
1365                         _tr_params_str.s = (char*)pkg_malloc((val->rs.len+1)*sizeof(char));
1366                         if(_tr_params_str.s==NULL)
1367                         {
1368                                 LM_ERR("no more private memory\n");
1369                                 memset(&_tr_params_str, 0, sizeof(str));
1370                                 if(_tr_params_list != NULL)
1371                                 {
1372                                         free_params(_tr_params_list);
1373                                         _tr_params_list = 0;
1374                                 }
1375                                 return -1;
1376                         }
1377                 }
1378                 _tr_params_str.len = val->rs.len;
1379                 memcpy(_tr_params_str.s, val->rs.s, val->rs.len);
1380                 _tr_params_str.s[_tr_params_str.len] = '\0';
1381
1382                 /* reset old values */
1383                 if(_tr_params_list != NULL)
1384                 {
1385                         free_params(_tr_params_list);
1386                         _tr_params_list = 0;
1387                 }
1388
1389                 /* parse params */
1390                 sv = _tr_params_str;
1391                 if (parse_params2(&sv, CLASS_ANY, &phooks, &_tr_params_list,
1392                                         _tr_params_separator)<0)
1393                         return -1;
1394         }
1395
1396         if(_tr_params_list==NULL)
1397                 return -1;
1398
1399         memset(val, 0, sizeof(pv_value_t));
1400         val->flags = PV_VAL_STR;
1401
1402         switch(subtype)
1403         {
1404                 case TR_PL_VALUE:
1405                         if(tp==NULL)
1406                         {
1407                                 LM_ERR("value invalid parameters\n");
1408                                 return -1;
1409                         }
1410
1411                         if(tp->type==TR_PARAM_STRING)
1412                         {
1413                                 sv = tp->v.s;
1414                         } else {
1415                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
1416                                                 || (!(v.flags&PV_VAL_STR)) || v.rs.len<=0)
1417                                 {
1418                                         LM_ERR("value cannot get p1\n");
1419                                         return -1;
1420                                 }
1421                                 sv = v.rs;
1422                         }
1423
1424                         for (pit = _tr_params_list; pit; pit=pit->next)
1425                         {
1426                                 if (pit->name.len==sv.len
1427                                                 && strncasecmp(pit->name.s, sv.s, sv.len)==0)
1428                                 {
1429                                         val->rs = pit->body;
1430                                         goto done;
1431                                 }
1432                         }
1433                         val->rs = _tr_empty;
1434                         break;
1435
1436                 case TR_PL_VALUEAT:
1437                         if(tp==NULL)
1438                         {
1439                                 LM_ERR("name invalid parameters\n");
1440                                 return -1;
1441                         }
1442
1443                         if(tp->type==TR_PARAM_NUMBER)
1444                         {
1445                                 n = tp->v.n;
1446                         } else {
1447                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
1448                                                 || (!(v.flags&PV_VAL_INT)))
1449                                 {
1450                                         LM_ERR("name cannot get p1\n");
1451                                         return -1;
1452                                 }
1453                                 n = v.ri;
1454                         }
1455                         if(n<0)
1456                         {
1457                                 n = -n;
1458                                 n--;
1459                                 for (pit = _tr_params_list; pit; pit=pit->next)
1460                                 {
1461                                         if(n==0)
1462                                         {
1463                                                 val->rs = pit->body;
1464                                                 goto done;
1465                                         }
1466                                         n--;
1467                                 }
1468                         } else {
1469                                 /* ugly hack -- params are in reverse order
1470                                  * - first count then find */
1471                                 i = 0;
1472                                 for (pit = _tr_params_list; pit; pit=pit->next)
1473                                         i++;
1474                                 if(n<i)
1475                                 {
1476                                         n = i - n - 1;
1477                                         for (pit = _tr_params_list; pit; pit=pit->next)
1478                                         {
1479                                                 if(n==0)
1480                                                 {
1481                                                         val->rs = pit->body;
1482                                                         goto done;
1483                                                 }
1484                                                 n--;
1485                                         }
1486                                 }
1487                         }
1488                         val->rs = _tr_empty;
1489                         break;
1490
1491                 case TR_PL_NAME:
1492                         if(tp==NULL)
1493                         {
1494                                 LM_ERR("name invalid parameters\n");
1495                                 return -1;
1496                         }
1497
1498                         if(tp->type==TR_PARAM_NUMBER)
1499                         {
1500                                 n = tp->v.n;
1501                         } else {
1502                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
1503                                                 || (!(v.flags&PV_VAL_INT)))
1504                                 {
1505                                         LM_ERR("name cannot get p1\n");
1506                                         return -1;
1507                                 }
1508                                 n = v.ri;
1509                         }
1510                         if(n<0)
1511                         {
1512                                 n = -n;
1513                                 n--;
1514                                 for (pit = _tr_params_list; pit; pit=pit->next)
1515                                 {
1516                                         if(n==0)
1517                                         {
1518                                                 val->rs = pit->name;
1519                                                 goto done;
1520                                         }
1521                                         n--;
1522                                 }
1523                         } else {
1524                                 /* ugly hack -- params are in reverse order
1525                                  * - first count then find */
1526                                 i = 0;
1527                                 for (pit = _tr_params_list; pit; pit=pit->next)
1528                                         i++;
1529                                 if(n<i)
1530                                 {
1531                                         n = i - n - 1;
1532                                         for (pit = _tr_params_list; pit; pit=pit->next)
1533                                         {
1534                                                 if(n==0)
1535                                                 {
1536                                                         val->rs = pit->name;
1537                                                         goto done;
1538                                                 }
1539                                                 n--;
1540                                         }
1541                                 }
1542                         }
1543                         val->rs = _tr_empty;
1544                         break;
1545
1546                 case TR_PL_COUNT:
1547                         val->ri = 0;
1548                         for (pit = _tr_params_list; pit; pit=pit->next)
1549                                 val->ri++;
1550                         val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
1551                         val->rs.s = int2str(val->ri, &val->rs.len);
1552                         break;
1553
1554                 default:
1555                         LM_ERR("unknown subtype %d\n",
1556                                         subtype);
1557                         return -1;
1558         }
1559 done:
1560         return 0;
1561 }
1562
1563 static str _tr_nameaddr_str = {0, 0};
1564 static name_addr_t _tr_nameaddr;
1565
1566
1567 /*!
1568  * \brief Evaluate name-address transformations
1569  * \param msg SIP message
1570  * \param tp transformation
1571  * \param subtype transformation type
1572  * \param val pseudo-variable
1573  * \return 0 on success, -1 on error
1574  */
1575 int tr_eval_nameaddr(struct sip_msg *msg, tr_param_t *tp, int subtype,
1576                 pv_value_t *val)
1577 {
1578         str sv;
1579         int ret;
1580
1581         if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
1582                 return -1;
1583
1584         if(_tr_nameaddr_str.len==0 || _tr_nameaddr_str.len!=val->rs.len ||
1585                         strncmp(_tr_nameaddr_str.s, val->rs.s, val->rs.len)!=0)
1586         {
1587                 if(val->rs.len>_tr_nameaddr_str.len)
1588                 {
1589                         if(_tr_nameaddr_str.s)
1590                                 pkg_free(_tr_nameaddr_str.s);
1591                         _tr_nameaddr_str.s = (char*)pkg_malloc((val->rs.len+1)*sizeof(char));
1592
1593                         if(_tr_nameaddr_str.s==NULL)
1594                         {
1595                                 LM_ERR("no more private memory\n");
1596                                 memset(&_tr_nameaddr_str, 0, sizeof(str));
1597                                 memset(&_tr_nameaddr, 0, sizeof(name_addr_t));
1598                                 return -1;
1599                         }
1600                 }
1601                 _tr_nameaddr_str.len = val->rs.len;
1602                 memcpy(_tr_nameaddr_str.s, val->rs.s, val->rs.len);
1603                 _tr_nameaddr_str.s[_tr_nameaddr_str.len] = '\0';
1604
1605                 /* reset old values */
1606                 memset(&_tr_nameaddr, 0, sizeof(name_addr_t));
1607
1608                 /* parse params */
1609                 sv = _tr_nameaddr_str;
1610                 ret = parse_nameaddr(&sv, &_tr_nameaddr);
1611                 if (ret < 0) {
1612                         if(ret != -3) return -1;
1613                         /* -3 means no "<" found so treat whole nameaddr as an URI */
1614                         _tr_nameaddr.uri = _tr_nameaddr_str;
1615                         _tr_nameaddr.name = _tr_empty;
1616                         _tr_nameaddr.len = _tr_nameaddr_str.len;
1617                 }
1618         }
1619
1620         memset(val, 0, sizeof(pv_value_t));
1621         val->flags = PV_VAL_STR;
1622
1623         switch(subtype)
1624         {
1625                 case TR_NA_URI:
1626                         val->rs = (_tr_nameaddr.uri.s)?_tr_nameaddr.uri:_tr_empty;
1627                         break;
1628                 case TR_NA_LEN:
1629                         val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
1630                         val->ri = _tr_nameaddr.len;
1631                         val->rs.s = int2str(val->ri, &val->rs.len);
1632                         break;
1633                 case TR_NA_NAME:
1634                         val->rs = (_tr_nameaddr.name.s)?_tr_nameaddr.name:_tr_empty;
1635                         break;
1636
1637                 default:
1638                         LM_ERR("unknown subtype %d\n",
1639                                         subtype);
1640                         return -1;
1641         }
1642         return 0;
1643 }
1644
1645 static str _tr_tobody_str = {0, 0};
1646 static struct to_body _tr_tobody = {0};
1647
1648 /*!
1649  * \brief Evaluate To-Body transformations
1650  * \param msg SIP message
1651  * \param tp transformation
1652  * \param subtype transformation type
1653  * \param val pseudo-variable
1654  * \return 0 on success, -1 on error
1655  */
1656 int tr_eval_tobody(struct sip_msg *msg, tr_param_t *tp, int subtype,
1657                 pv_value_t *val)
1658 {
1659         str sv;
1660
1661         if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
1662                 return -1;
1663
1664         if(_tr_tobody_str.len==0 || _tr_tobody_str.len!=val->rs.len ||
1665                         strncmp(_tr_tobody_str.s, val->rs.s, val->rs.len)!=0)
1666         {
1667                 if(_tr_tobody_str.s==NULL || val->rs.len>_tr_tobody_str.len)
1668                 {
1669                         if(_tr_tobody_str.s)
1670                                 pkg_free(_tr_tobody_str.s);
1671                         _tr_tobody_str.s = (char*)pkg_malloc((val->rs.len+3)*sizeof(char));
1672
1673                         if(_tr_tobody_str.s==NULL)
1674                         {
1675                                 LM_ERR("no more private memory\n");
1676                                 free_to_params(&_tr_tobody);
1677                                 memset(&_tr_tobody, 0, sizeof(struct to_body));
1678                                 memset(&_tr_tobody_str, 0, sizeof(str));
1679                                 return -1;
1680                         }
1681                 }
1682                 _tr_tobody_str.len = val->rs.len;
1683                 memcpy(_tr_tobody_str.s, val->rs.s, val->rs.len);
1684                 _tr_tobody_str.s[_tr_tobody_str.len] = '\r';
1685                 _tr_tobody_str.s[_tr_tobody_str.len+1] = '\n';
1686                 _tr_tobody_str.s[_tr_tobody_str.len+2] = '\0';
1687
1688                 /* reset old values */
1689                 free_to_params(&_tr_tobody);
1690                 memset(&_tr_tobody, 0, sizeof(struct to_body));
1691
1692                 /* parse params */
1693                 sv = _tr_tobody_str;
1694                 parse_to(sv.s, sv.s + sv.len + 2, &_tr_tobody);
1695                 if (_tr_tobody.error == PARSE_ERROR)
1696                 {
1697                         free_to_params(&_tr_tobody);
1698                         memset(&_tr_tobody, 0, sizeof(struct to_body));
1699                         pkg_free(_tr_tobody_str.s);
1700                         memset(&_tr_tobody_str, 0, sizeof(str));
1701                         return -1;
1702                 }
1703                 if (parse_uri(_tr_tobody.uri.s, _tr_tobody.uri.len,
1704                                         &_tr_tobody.parsed_uri)<0)
1705                 {
1706                         free_to_params(&_tr_tobody);
1707                         memset(&_tr_tobody, 0, sizeof(struct to_body));
1708                         pkg_free(_tr_tobody_str.s);
1709                         memset(&_tr_tobody_str, 0, sizeof(str));
1710                         return -1;
1711                 }
1712         }
1713
1714         memset(val, 0, sizeof(pv_value_t));
1715         val->flags = PV_VAL_STR;
1716
1717         switch(subtype)
1718         {
1719                 case TR_TOBODY_URI:
1720                         val->rs = (_tr_tobody.uri.s)?_tr_tobody.uri:_tr_empty;
1721                         break;
1722                 case TR_TOBODY_TAG:
1723                         val->rs = (_tr_tobody.tag_value.s)?_tr_tobody.tag_value:_tr_empty;
1724                         break;
1725                 case TR_TOBODY_DISPLAY:
1726                         val->rs = (_tr_tobody.display.s)?_tr_tobody.display:_tr_empty;
1727                         break;
1728                 case TR_TOBODY_URI_USER:
1729                         val->rs = (_tr_tobody.parsed_uri.user.s)
1730                                 ?_tr_tobody.parsed_uri.user:_tr_empty;
1731                         break;
1732                 case TR_TOBODY_URI_HOST:
1733                         val->rs = (_tr_tobody.parsed_uri.host.s)
1734                                 ?_tr_tobody.parsed_uri.host:_tr_empty;
1735                         break;
1736                 case TR_TOBODY_PARAMS:
1737                         if(_tr_tobody.param_lst!=NULL)
1738                         {
1739                                 val->rs.s = _tr_tobody.param_lst->name.s;
1740                                 val->rs.len = _tr_tobody_str.s + _tr_tobody_str.len
1741                                         - val->rs.s;
1742                         } else val->rs = _tr_empty;
1743                         break;
1744
1745                 default:
1746                         LM_ERR("unknown subtype %d\n", subtype);
1747                         return -1;
1748         }
1749         return 0;
1750 }
1751
1752 void *memfindrchr(const void *buf, int c, size_t n)
1753 {
1754         int i;
1755         unsigned char *p;
1756
1757         p = (unsigned char*)buf;
1758
1759         for (i=n-1; i>=0; i--) {
1760                 if (p[i] == (unsigned char)c) {
1761                         return (void*)(p+i);
1762                 }
1763         }
1764         return NULL;
1765 }
1766
1767 /*!
1768  * \brief Evaluate line transformations
1769  * \param msg SIP message
1770  * \param tp transformation
1771  * \param subtype transformation type
1772  * \param val pseudo-variable
1773  * \return 0 on success, -1 on error
1774  */
1775 int tr_eval_line(struct sip_msg *msg, tr_param_t *tp, int subtype,
1776                 pv_value_t *val)
1777 {
1778         pv_value_t v;
1779         str sv;
1780         str mv;
1781         char *p;
1782         int n, i;
1783
1784         if(val==NULL || (!(val->flags&PV_VAL_STR)) || val->rs.len<=0)
1785                 return -1;
1786
1787         switch(subtype)
1788         {
1789                 case TR_LINE_SW:
1790                         if(tp==NULL)
1791                         {
1792                                 LM_ERR("value invalid parameters\n");
1793                                 return -1;
1794                         }
1795
1796                         if(tp->type==TR_PARAM_STRING)
1797                         {
1798                                 sv = tp->v.s;
1799                         } else {
1800                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
1801                                                 || (!(v.flags&PV_VAL_STR)) || v.rs.len<=0)
1802                                 {
1803                                         LM_ERR("value cannot get p1\n");
1804                                         return -1;
1805                                 }
1806                                 sv = v.rs;
1807                         }
1808
1809                         if(val->rs.len < sv.len)
1810                         {
1811                                 val->rs = _tr_empty;
1812                                 goto done;
1813                         }
1814                         p = val->rs.s;
1815                         do {
1816                                 if(strncmp(p, sv.s, sv.len)==0)
1817                                 {
1818                                         /* match */
1819                                         mv.s = p;
1820                                         p += sv.len;
1821                                         p = memchr(p, '\n', (val->rs.s + val->rs.len) - p);
1822                                         if(p==NULL)
1823                                         {
1824                                                 /* last line */
1825                                                 mv.len = (val->rs.s + val->rs.len) - mv.s;
1826                                         } else {
1827                                                 mv.len = p - mv.s;
1828                                         }
1829                                         val->rs = mv;
1830                                         goto done;
1831                                 }
1832                                 p = memchr(p, '\n', (val->rs.s + val->rs.len) - p);
1833                         } while(p && ((++p)<=val->rs.s+val->rs.len-sv.len));
1834                         val->rs = _tr_empty;
1835                         break;
1836
1837                 case TR_LINE_AT:
1838                         if(tp==NULL)
1839                         {
1840                                 LM_ERR("name invalid parameters\n");
1841                                 return -1;
1842                         }
1843
1844                         if(tp->type==TR_PARAM_NUMBER)
1845                         {
1846                                 n = tp->v.n;
1847                         } else {
1848                                 if(pv_get_spec_value(msg, (pv_spec_p)tp->v.data, &v)!=0
1849                                                 || (!(v.flags&PV_VAL_INT)))
1850                                 {
1851                                         LM_ERR("name cannot get p1\n");
1852                                         return -1;
1853                                 }
1854                                 n = v.ri;
1855                         }
1856                         if(n<0)
1857                         {
1858                                 p = val->rs.s + val->rs.len - 1;
1859                                 if(*p=='\n')
1860                                         p--;
1861                                 mv.s = p;
1862                                 n = -n;
1863                                 i=1;
1864                                 p = memfindrchr(val->rs.s, '\n', p - val->rs.s);
1865                                 if(p!=NULL)
1866                                         p--;
1867                                 while(i<n && p)
1868                                 {
1869                                         mv.s = p;
1870                                         p = memfindrchr(val->rs.s, '\n', p - val->rs.s);
1871                                         if(p!=NULL)
1872                                                 p--;
1873                                         i++;
1874                                 }
1875                                 if(i==n)
1876                                 {
1877                                         if(p==NULL)
1878                                         {
1879                                                 /* first line */
1880                                                 mv.len = mv.s - val->rs.s + 1;
1881                                                 mv.s = val->rs.s;
1882                                         } else {
1883                                                 mv.len = mv.s - p - 1;
1884                                                 mv.s = p + 2;
1885                                         }
1886                                         val->rs = mv;
1887                                         goto done;
1888                                 }
1889                         } else {
1890                                 p = val->rs.s;
1891                                 i = 0;
1892                                 while(i<n && p)
1893                                 {
1894                                         p = memchr(p, '\n', (val->rs.s + val->rs.len) - p);
1895                                         if(p!=NULL)
1896                                                 p++;
1897                                         i++;
1898                                 }
1899                                 if(i==n && p!=NULL)
1900                                 {
1901                                         /* line found */
1902                                         mv.s = p;
1903                                         p = memchr(p, '\n', (val->rs.s + val->rs.len) - p);
1904                                         if(p==NULL)
1905                                         {
1906                                                 /* last line */
1907                                                 mv.len = (val->rs.s + val->rs.len) - mv.s;
1908                                         } else {
1909                                                 mv.len = p - mv.s;
1910                                         }
1911                                         val->rs = mv;
1912                                         goto done;
1913                                 }
1914                         }
1915                         val->rs = _tr_empty;
1916                         break;
1917
1918                 case TR_LINE_COUNT:
1919                         n=0;
1920                         for(i=0; i<val->rs.len; i++)
1921                                 if(val->rs.s[i]=='\n')
1922                                         n++;
1923                         if(n==0 && val->rs.len>0)
1924                                 n = 1;
1925                         val->flags = PV_TYPE_INT|PV_VAL_INT|PV_VAL_STR;
1926                         val->ri = n;
1927                         val->rs.s = int2str(val->ri, &val->rs.len);
1928                         break;
1929
1930                         break;
1931
1932                 default:
1933                         LM_ERR("unknown subtype %d\n",
1934                                         subtype);
1935                         return -1;
1936         }
1937 done:
1938         if(val->rs.len>0)
1939         {
1940                 /* skip ending '\r' if present */
1941                 if(val->rs.s[val->rs.len-1]=='\r')
1942                         val->rs.len--;
1943         }
1944         val->flags = PV_VAL_STR;
1945         return 0;
1946 }
1947
1948
1949 #define _tr_parse_nparam(_p, _p0, _tp, _spec, _n, _sign, _in, _s) \
1950         while(is_in_str(_p, _in) && (*_p==' ' || *_p=='\t' || *_p=='\n')) _p++; \
1951         if(*_p==PV_MARKER) \
1952         { /* pseudo-variable */ \
1953                 _spec = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t)); \
1954                 if(_spec==NULL) \
1955                 { \
1956                         LM_ERR("no more private memory!\n"); \
1957                         goto error; \
1958                 } \
1959                 _s.s = _p; _s.len = _in->s + _in->len - _p; \
1960                 _p0 = pv_parse_spec(&_s, _spec); \
1961                 if(_p0==NULL) \
1962                 { \
1963                         LM_ERR("invalid spec in substr transformation: %.*s!\n", \
1964                                         _in->len, _in->s); \
1965                         goto error; \
1966                 } \
1967                 _p = _p0; \
1968                 _tp = (tr_param_t*)pkg_malloc(sizeof(tr_param_t)); \
1969                 if(_tp==NULL) \
1970                 { \
1971                         LM_ERR("no more private memory!\n"); \
1972                         goto error; \
1973                 } \
1974                 memset(_tp, 0, sizeof(tr_param_t)); \
1975                 _tp->type = TR_PARAM_SPEC; \
1976                 _tp->v.data = (void*)_spec; \
1977         } else { \
1978                 if(*_p=='+' || *_p=='-' || (*_p>='0' && *_p<='9')) \
1979                 { /* number */ \
1980                         _sign = 1; \
1981                         if(*_p=='-') { \
1982                                 _p++; \
1983                                 _sign = -1; \
1984                         } else if(*_p=='+') _p++; \
1985                         _n = 0; \
1986                         while(is_in_str(_p, _in) && (*_p==' ' || *_p=='\t' || *_p=='\n')) \
1987                         _p++; \
1988                         while(is_in_str(_p, _in) && *_p>='0' && *_p<='9') \
1989                         { \
1990                                 _n = _n*10 + *_p - '0'; \
1991                                 _p++; \
1992                         } \
1993                         _tp = (tr_param_t*)pkg_malloc(sizeof(tr_param_t)); \
1994                         if(_tp==NULL) \
1995                         { \
1996                                 LM_ERR("no more private memory!\n"); \
1997                                 goto error; \
1998                         } \
1999                         memset(_tp, 0, sizeof(tr_param_t)); \
2000                         _tp->type = TR_PARAM_NUMBER; \
2001                         _tp->v.n = sign*n; \
2002                 } else { \
2003                         LM_ERR("tinvalid param in transformation: %.*s!!\n", \
2004                                         _in->len, _in->s); \
2005                         goto error; \
2006                 } \
2007         }
2008
2009 #define _tr_parse_sparam(_p, _p0, _tp, _spec, _ps, _in, _s) \
2010         while(is_in_str(_p, _in) && (*_p==' ' || *_p=='\t' || *_p=='\n')) _p++; \
2011         if(*_p==PV_MARKER) \
2012         { /* pseudo-variable */ \
2013                 _spec = (pv_spec_t*)pkg_malloc(sizeof(pv_spec_t)); \
2014                 if(_spec==NULL) \
2015                 { \
2016                         LM_ERR("no more private memory!\n"); \
2017                         goto error; \
2018                 } \
2019                 _s.s = _p; _s.len = _in->s + _in->len - _p; \
2020                 _p0 = pv_parse_spec(&_s, _spec); \
2021                 if(_p0==NULL) \
2022                 { \
2023                         LM_ERR("invalid spec in substr transformation: %.*s!\n", \
2024                                         _in->len, _in->s); \
2025                         goto error; \
2026                 } \
2027                 _p = _p0; \
2028                 _tp = (tr_param_t*)pkg_malloc(sizeof(tr_param_t)); \
2029                 if(_tp==NULL) \
2030                 { \
2031                         LM_ERR("no more private memory!\n"); \
2032                         goto error; \
2033                 } \
2034                 memset(_tp, 0, sizeof(tr_param_t)); \
2035                 _tp->type = TR_PARAM_SPEC; \
2036                 _tp->v.data = (void*)_spec; \
2037         } else { /* string */ \
2038                 _ps = _p; \
2039                 while(is_in_str(_p, _in) && *_p!='\t' && *_p!='\n' \
2040                                 && *_p!=TR_PARAM_MARKER && *_p!=TR_RBRACKET) \
2041                 _p++; \
2042                 if(*_p=='\0') \
2043                 { \
2044                         LM_ERR("invalid param in transformation: %.*s!!\n", \
2045                                         _in->len, _in->s); \
2046                         goto error; \
2047                 } \
2048                 _tp = (tr_param_t*)pkg_malloc(sizeof(tr_param_t)); \
2049                 if(_tp==NULL) \
2050                 { \
2051                         LM_ERR("no more private memory!\n"); \
2052                         goto error; \
2053                 } \
2054                 memset(_tp, 0, sizeof(tr_param_t)); \
2055                 _tp->type = TR_PARAM_STRING; \
2056                 _tp->v.s.s = _ps; \
2057                 _tp->v.s.len = _p - _ps; \
2058         }
2059
2060
2061 /*!
2062  * \brief Helper fuction to parse a string transformation
2063  * \param in parsed string
2064  * \param t transformation
2065  * \return pointer to the end of the transformation in the string - '}', null on error
2066  */
2067 char* tr_parse_string(str* in, trans_t *t)
2068 {
2069         char *p;
2070         char *p0;
2071         char *ps;
2072         str name;
2073         str s;
2074         pv_spec_t *spec = NULL;
2075         int n;
2076         int sign;
2077         tr_param_t *tp = NULL;
2078
2079         if(in==NULL || t==NULL)
2080                 return NULL;
2081
2082         p = in->s;
2083         name.s = in->s;
2084         t->type = TR_STRING;
2085         t->trf = tr_eval_string;
2086
2087         /* find next token */
2088         while(is_in_str(p, in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
2089         if(*p=='\0')
2090         {
2091                 LM_ERR("invalid transformation: %.*s\n",
2092                                 in->len, in->s);
2093                 goto error;
2094         }
2095         name.len = p - name.s;
2096         trim(&name);
2097
2098         if(name.len==3 && strncasecmp(name.s, "len", 3)==0)
2099         {
2100                 t->subtype = TR_S_LEN;
2101                 goto done;
2102         } else if(name.len==3 && strncasecmp(name.s, "int", 3)==0) {
2103                 t->subtype = TR_S_INT;
2104                 goto done;
2105         } else if(name.len==3 && strncasecmp(name.s, "md5", 3)==0) {
2106                 t->subtype = TR_S_MD5;
2107                 goto done;
2108         } else if(name.len==6 && strncasecmp(name.s, "sha256", 6)==0) {
2109                 t->subtype = TR_S_SHA256;
2110                 goto done;
2111         } else if(name.len==6 && strncasecmp(name.s, "sha384", 6)==0) {
2112                 t->subtype = TR_S_SHA384;
2113                 goto done;
2114         } else if(name.len==6 && strncasecmp(name.s, "sha512", 6)==0) {
2115                 t->subtype = TR_S_SHA512;
2116                 goto done;
2117         } else if(name.len==7 && strncasecmp(name.s, "tolower", 7)==0) {
2118                 t->subtype = TR_S_TOLOWER;
2119                 goto done;
2120         } else if(name.len==7 && strncasecmp(name.s, "toupper", 7)==0) {
2121                 t->subtype = TR_S_TOUPPER;
2122                 goto done;
2123         } else if(name.len==7 && strncasecmp(name.s, "numeric", 7)==0) {
2124                 t->subtype = TR_S_NUMERIC;
2125                 goto done;
2126         } else if(name.len==11 && strncasecmp(name.s, "encode.hexa", 11)==0) {
2127                 t->subtype = TR_S_ENCODEHEXA;
2128                 goto done;
2129         } else if(name.len==11 && strncasecmp(name.s, "decode.hexa", 11)==0) {
2130                 t->subtype = TR_S_DECODEHEXA;
2131                 goto done;
2132         } else if(name.len==11 && strncasecmp(name.s, "encode.7bit", 11)==0) {
2133                 t->subtype = TR_S_ENCODE7BIT;
2134                 goto done;
2135         } else if(name.len==11 && strncasecmp(name.s, "decode.7bit", 11)==0) {
2136                 t->subtype = TR_S_DECODE7BIT;
2137                 goto done;
2138         } else if(name.len==13 && strncasecmp(name.s, "encode.base58", 13)==0) {
2139                 t->subtype = TR_S_ENCODEBASE58;
2140                 goto done;
2141         } else if(name.len==13 && strncasecmp(name.s, "decode.base58", 13)==0) {
2142                 t->subtype = TR_S_DECODEBASE58;
2143                 goto done;
2144         } else if(name.len==13 && strncasecmp(name.s, "encode.base64", 13)==0) {
2145                 t->subtype = TR_S_ENCODEBASE64;
2146                 goto done;
2147         } else if(name.len==13 && strncasecmp(name.s, "decode.base64", 13)==0) {
2148                 t->subtype = TR_S_DECODEBASE64;
2149                 goto done;
2150         } else if(name.len==13 && strncasecmp(name.s, "escape.common", 13)==0) {
2151                 t->subtype = TR_S_ESCAPECOMMON;
2152                 goto done;
2153         } else if(name.len==15 && strncasecmp(name.s, "unescape.common", 15)==0) {
2154                 t->subtype = TR_S_UNESCAPECOMMON;
2155                 goto done;
2156         } else if(name.len==11 && strncasecmp(name.s, "escape.user", 11)==0) {
2157                 t->subtype = TR_S_ESCAPEUSER;
2158                 goto done;
2159         } else if(name.len==13 && strncasecmp(name.s, "unescape.user", 13)==0) {
2160                 t->subtype = TR_S_UNESCAPEUSER;
2161                 goto done;
2162         } else if(name.len==12 && strncasecmp(name.s, "escape.param", 12)==0) {
2163                 t->subtype = TR_S_ESCAPEPARAM;
2164                 goto done;
2165         } else if(name.len==14 && strncasecmp(name.s, "unescape.param", 14)==0) {
2166                 t->subtype = TR_S_UNESCAPEPARAM;
2167                 goto done;
2168         } else if(name.len==10 && strncasecmp(name.s, "escape.csv", 10)==0) {
2169                 t->subtype = TR_S_ESCAPECSV;
2170                 goto done;
2171         } else if(name.len==8 && strncasecmp(name.s, "prefixes", 8)==0) {
2172                 t->subtype = TR_S_PREFIXES;
2173                 if(*p!=TR_PARAM_MARKER)
2174                         goto done;
2175                 p++;
2176                 _tr_parse_nparam(p, p0, tp, spec, n, sign, in, s);
2177                 t->params = tp;
2178                 tp = 0;
2179                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2180                 if(*p!=TR_RBRACKET)
2181                 {
2182                         LM_ERR("invalid prefixes transformation: %.*s!!\n",
2183                                         in->len, in->s);
2184                         goto error;
2185                 }
2186                 goto done;
2187         } else if(name.len==15 && strncasecmp(name.s, "prefixes.quoted", 15)==0) {
2188                 t->subtype = TR_S_PREFIXES_QUOT;
2189                 if(*p!=TR_PARAM_MARKER)
2190                         goto done;
2191                 p++;
2192                 _tr_parse_nparam(p, p0, tp, spec, n, sign, in, s);
2193                 t->params = tp;
2194                 tp = 0;
2195                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2196                 if(*p!=TR_RBRACKET)
2197                 {
2198                         LM_ERR("invalid prefixes transformation: %.*s!!\n",
2199                                         in->len, in->s);
2200                         goto error;
2201                 }
2202                 goto done;
2203         } else if(name.len==6 && strncasecmp(name.s, "substr", 6)==0) {
2204                 t->subtype = TR_S_SUBSTR;
2205                 if(*p!=TR_PARAM_MARKER)
2206                 {
2207                         LM_ERR("invalid substr transformation: %.*s!\n", in->len, in->s);
2208                         goto error;
2209                 }
2210                 p++;
2211                 _tr_parse_nparam(p, p0, tp, spec, n, sign, in, s);
2212                 t->params = tp;
2213                 tp = 0;
2214                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2215                 if(*p!=TR_PARAM_MARKER)
2216                 {
2217                         LM_ERR("invalid substr transformation: %.*s!\n",
2218                                         in->len, in->s);
2219                         goto error;
2220                 }
2221                 p++;
2222                 _tr_parse_nparam(p, p0, tp, spec, n, sign, in, s);
2223                 if(tp->type==TR_PARAM_NUMBER && tp->v.n<0)
2224                 {
2225                         LM_ERR("substr negative offset\n");
2226                         goto error;
2227                 }
2228                 t->params->next = tp;
2229                 tp = 0;
2230                 while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2231                 if(*p!=TR_RBRACKET)
2232                 {
2233                         LM_ERR("invalid substr transformation: %.*s!!\n",
2234                                         in->len, in->s);
2235                         goto error;
2236                 }
2237                 goto done;
2238         } else if(name.len==6 && strncasecmp(name.s, "select", 6)==0) {
2239                 t->subtype = TR_S_SELECT;
2240                 if(*p!=TR_PARAM_MARKER)
2241                 {
2242                         LM_ERR("invalid select transformation: %.*s!\n",
2243                                         in->len, in->s);
2244                         goto error;
2245                 }
2246                 p++;
2247                 _tr_parse_nparam(p, p0, tp, spec, n, sign, in, s);
2248                 t->params = tp;
2249                 tp = 0;
2250                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2251                 if(*p!=TR_PARAM_MARKER || *(p+1)=='\0')
2252                 {
2253                         LM_ERR("invalid select transformation: %.*s!\n", in->len, in->s);
2254                         goto error;
2255                 }
2256                 p++;
2257                 tp = (tr_param_t*)pkg_malloc(sizeof(tr_param_t));
2258                 if(tp==NULL)
2259                 {
2260                         LM_ERR("no more private memory!\n");
2261                         goto error;
2262                 }
2263                 memset(tp, 0, sizeof(tr_param_t));
2264                 tp->type = TR_PARAM_STRING;
2265                 tp->v.s.s = p;
2266                 tp->v.s.len = 1;
2267                 t->params->next = tp;
2268                 tp = 0;
2269                 p++;
2270                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2271                 if(*p!=TR_RBRACKET)
2272                 {
2273                         LM_ERR("invalid select transformation: %.*s!!\n",
2274                                         in->len, in->s);
2275                         goto error;
2276                 }
2277                 goto done;
2278         } else if(name.len==5 && strncasecmp(name.s, "strip", 5)==0) {
2279                 t->subtype = TR_S_STRIP;
2280                 if(*p!=TR_PARAM_MARKER)
2281                 {
2282                         LM_ERR("invalid strip transformation: %.*s!\n",
2283                                         in->len, in->s);
2284                         goto error;
2285                 }
2286                 p++;
2287                 _tr_parse_nparam(p, p0, tp, spec, n, sign, in, s);
2288                 t->params = tp;
2289                 tp = 0;
2290                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2291                 if(*p!=TR_RBRACKET)
2292                 {
2293                         LM_ERR("invalid strip transformation: %.*s!!\n",
2294                                         in->len, in->s);
2295                         goto error;
2296                 }
2297                 goto done;
2298         } else if(name.len==9 && strncasecmp(name.s, "striptail", 9)==0) {
2299                 t->subtype = TR_S_STRIPTAIL;
2300                 if(*p!=TR_PARAM_MARKER)
2301                 {
2302                         LM_ERR("invalid striptail transformation: %.*s!\n",
2303                                         in->len, in->s);
2304                         goto error;
2305                 }
2306                 p++;
2307                 _tr_parse_nparam(p, p0, tp, spec, n, sign, in, s);
2308                 t->params = tp;
2309                 tp = 0;
2310                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2311                 if(*p!=TR_RBRACKET)
2312                 {
2313                         LM_ERR("invalid striptail transformation: %.*s!!\n",
2314                                         in->len, in->s);
2315                         goto error;
2316                 }
2317                 goto done;
2318         } else if(name.len==7 && strncasecmp(name.s, "stripto", 7)==0) {
2319                 t->subtype = TR_S_STRIPTO;
2320                 if(*p!=TR_PARAM_MARKER)
2321                 {
2322                         LM_ERR("invalid stripto transformation: %.*s!\n",
2323                                         in->len, in->s);
2324                         goto error;
2325                 }
2326                 p++;
2327                 _tr_parse_sparam(p, p0, tp, spec, ps, in, s);
2328                 t->params = tp;
2329                 tp = 0;
2330                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2331                 if(*p!=TR_RBRACKET)
2332                 {
2333                         LM_ERR("invalid strip transformation: %.*s!!\n",
2334                                         in->len, in->s);
2335                         goto error;
2336                 }
2337                 goto done;
2338         } else if(name.len==5 && strncasecmp(name.s, "ftime", 5)==0) {
2339                 t->subtype = TR_S_TIMEFORMAT;
2340                 if(*p!=TR_PARAM_MARKER)
2341                 {
2342                         LM_ERR("invalid ftime transformation: %.*s!\n",
2343                                         in->len, in->s);
2344                         goto error;
2345                 }
2346                 p++;
2347                 _tr_parse_sparam(p, p0, tp, spec, ps, in, s);
2348                 t->params = tp;
2349                 tp = 0;
2350                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2351                 if(*p!=TR_RBRACKET)
2352                 {
2353                         LM_ERR("invalid ftime transformation: %.*s!!\n",
2354                                         in->len, in->s);
2355                         goto error;
2356                 }
2357                 goto done;
2358         } else if(name.len==7 && strncasecmp(name.s, "replace", 7)==0) {
2359                 t->subtype = TR_S_REPLACE;
2360                 if(*p!=TR_PARAM_MARKER)
2361                 {
2362                         LM_ERR("invalid replace transformation: %.*s!\n", in->len, in->s);
2363                         goto error;
2364                 }
2365                 p++;
2366                 _tr_parse_sparam(p, p0, tp, spec, ps, in, s);
2367                 t->params = tp;
2368                 tp = 0;
2369                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2370                 if(*p!=TR_PARAM_MARKER)
2371                 {
2372                         LM_ERR("invalid replace transformation: %.*s!\n",
2373                                         in->len, in->s);
2374                         goto error;
2375                 }
2376                 p++;
2377                 _tr_parse_sparam(p, p0, tp, spec, ps, in, s);
2378                 t->params->next = tp;
2379                 tp = 0;
2380                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2381                 if(*p!=TR_RBRACKET)
2382                 {
2383                         LM_ERR("invalid replace transformation: %.*s!!\n",
2384                                         in->len, in->s);
2385                         goto error;
2386                 }
2387                 goto done;
2388         } else if(name.len==4 && strncasecmp(name.s, "trim", 4)==0) {
2389                 t->subtype = TR_S_TRIM;
2390                 goto done;
2391         } else if(name.len==5 && strncasecmp(name.s, "rtrim", 5)==0) {
2392                 t->subtype = TR_S_RTRIM;
2393                 goto done;
2394         } else if(name.len==5 && strncasecmp(name.s, "ltrim", 5)==0) {
2395                 t->subtype = TR_S_LTRIM;
2396                 goto done;
2397         } else if(name.len==2 && strncasecmp(name.s, "rm", 2)==0) {
2398                 t->subtype = TR_S_RM;
2399                 if(*p!=TR_PARAM_MARKER)
2400                 {
2401                         LM_ERR("invalid ftime transformation: %.*s!\n",
2402                                         in->len, in->s);
2403                         goto error;
2404                 }
2405                 p++;
2406                 _tr_parse_sparam(p, p0, tp, spec, ps, in, s);
2407                 t->params = tp;
2408                 tp = 0;
2409                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2410                 if(*p!=TR_RBRACKET)
2411                 {
2412                         LM_ERR("invalid ftime transformation: %.*s!!\n",
2413                                         in->len, in->s);
2414                         goto error;
2415                 }
2416                 goto done;
2417         } else if(name.len==15 && strncasecmp(name.s, "urlencode.param", 15)==0) {
2418                 t->subtype = TR_S_URLENCODEPARAM;
2419                 goto done;
2420         } else if(name.len==15 && strncasecmp(name.s, "urldecode.param", 15)==0) {
2421                 t->subtype = TR_S_URLDECODEPARAM;
2422                 goto done;
2423         }
2424
2425         LM_ERR("unknown transformation: %.*s/%.*s/%d!\n", in->len, in->s,
2426                         name.len, name.s, name.len);
2427 error:
2428         if(tp)
2429                 tr_param_free(tp);
2430         if(spec)
2431                 pv_spec_free(spec);
2432         return NULL;
2433 done:
2434         t->name = name;
2435         return p;
2436 }
2437
2438
2439 /*!
2440  * \brief Helper fuction to parse a URI transformation
2441  * \param in parsed string
2442  * \param t transformation
2443  * \return pointer to the end of the transformation in the string - '}', null on error
2444  */
2445 char* tr_parse_uri(str* in, trans_t *t)
2446 {
2447         char *p;
2448         char *p0;
2449         char *ps;
2450         str name;
2451         str s;
2452         pv_spec_t *spec = NULL;
2453         tr_param_t *tp = NULL;
2454
2455         if(in==NULL || in->s==NULL || t==NULL)
2456                 return NULL;
2457
2458         p = in->s;
2459         name.s = in->s;
2460         t->type = TR_URI;
2461         t->trf = tr_eval_uri;
2462
2463         /* find next token */
2464         while(*p && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
2465         if(*p=='\0')
2466         {
2467                 LM_ERR("invalid transformation: %.*s\n", in->len, in->s);
2468                 goto error;
2469         }
2470         name.len = p - name.s;
2471         trim(&name);
2472
2473         if(name.len==4 && strncasecmp(name.s, "user", 4)==0)
2474         {
2475                 t->subtype = TR_URI_USER;
2476                 goto done;
2477         } else if((name.len==4 && strncasecmp(name.s, "host", 4)==0)
2478                         || (name.len==6 && strncasecmp(name.s, "domain", 6)==0)) {
2479                 t->subtype = TR_URI_HOST;
2480                 goto done;
2481         } else if(name.len==6 && strncasecmp(name.s, "passwd", 6)==0) {
2482                 t->subtype = TR_URI_PASSWD;
2483                 goto done;
2484         } else if(name.len==4 && strncasecmp(name.s, "port", 4)==0) {
2485                 t->subtype = TR_URI_PORT;
2486                 goto done;
2487         } else if(name.len==6 && strncasecmp(name.s, "params", 6)==0) {
2488                 t->subtype = TR_URI_PARAMS;
2489                 goto done;
2490         } else if(name.len==7 && strncasecmp(name.s, "headers", 7)==0) {
2491                 t->subtype = TR_URI_HEADERS;
2492                 goto done;
2493         } else if(name.len==5 && strncasecmp(name.s, "param", 5)==0) {
2494                 t->subtype = TR_URI_PARAM;
2495                 if(*p!=TR_PARAM_MARKER)
2496                 {
2497                         LM_ERR("invalid param transformation: %.*s\n", in->len, in->s);
2498                         goto error;
2499                 }
2500                 p++;
2501                 _tr_parse_sparam(p, p0, tp, spec, ps, in, s);
2502                 t->params = tp;
2503                 tp = 0;
2504                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2505                 if(*p!=TR_RBRACKET)
2506                 {
2507                         LM_ERR("invalid param transformation: %.*s!\n", in->len, in->s);
2508                         goto error;
2509                 }
2510                 goto done;
2511         } else if(name.len==9 && strncasecmp(name.s, "transport", 9)==0) {
2512                 t->subtype = TR_URI_TRANSPORT;
2513                 goto done;
2514         } else if(name.len==3 && strncasecmp(name.s, "ttl", 3)==0) {
2515                 t->subtype = TR_URI_TTL;
2516                 goto done;
2517         } else if(name.len==6 && strncasecmp(name.s, "uparam", 6)==0) {
2518                 t->subtype = TR_URI_UPARAM;
2519                 goto done;
2520         } else if(name.len==5 && strncasecmp(name.s, "maddr", 5)==0) {
2521                 t->subtype = TR_URI_MADDR;
2522                 goto done;
2523         } else if(name.len==6 && strncasecmp(name.s, "method", 6)==0) {
2524                 t->subtype = TR_URI_METHOD;
2525                 goto done;
2526         } else if(name.len==2 && strncasecmp(name.s, "lr", 2)==0) {
2527                 t->subtype = TR_URI_LR;
2528                 goto done;
2529         } else if(name.len==2 && strncasecmp(name.s, "r2", 2)==0) {
2530                 t->subtype = TR_URI_R2;
2531                 goto done;
2532         }
2533
2534         LM_ERR("unknown transformation: %.*s/%.*s!\n", in->len,
2535                         in->s, name.len, name.s);
2536 error:
2537         if(tp)
2538                 tr_param_free(tp);
2539         if(spec)
2540                 pv_spec_free(spec);
2541         return NULL;
2542 done:
2543         t->name = name;
2544         return p;
2545 }
2546
2547
2548 /*!
2549  * \brief Helper fuction to parse a parameter transformation
2550  * \param in parsed string
2551  * \param t transformation
2552  * \return pointer to the end of the transformation in the string - '}', null on error
2553  */
2554 char* tr_parse_paramlist(str* in, trans_t *t)
2555 {
2556         char *p;
2557         char *p0;
2558         char *ps;
2559         char *start_pos;
2560         str s;
2561         str name;
2562         int n;
2563         int sign;
2564         pv_spec_t *spec = NULL;
2565         tr_param_t *tp = NULL;
2566
2567         if(in==NULL || in->s==NULL || t==NULL)
2568                 return NULL;
2569
2570         p = in->s;
2571         name.s = in->s;
2572         t->type = TR_PARAMLIST;
2573         t->trf = tr_eval_paramlist;
2574
2575         /* find next token */
2576         while(is_in_str(p, in) && *p!=TR_PARAM_MARKER && *p!=TR_RBRACKET) p++;
2577         if(*p=='\0')
2578         {
2579                 LM_ERR("invalid transformation: %.*s\n",
2580                                 in->len, in->s);
2581                 goto error;
2582         }
2583         name.len = p - name.s;
2584         trim(&name);
2585
2586         if(name.len==5 && strncasecmp(name.s, "value", 5)==0)
2587         {
2588                 t->subtype = TR_PL_VALUE;
2589                 if(*p!=TR_PARAM_MARKER)
2590                 {
2591                         LM_ERR("invalid value transformation: %.*s\n",
2592                                         in->len, in->s);
2593                         goto error;
2594                 }
2595                 p++;
2596                 _tr_parse_sparam(p, p0, tp, spec, ps, in, s);
2597                 t->params = tp;
2598                 tp = 0;
2599                 while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2600
2601                 if(*p==TR_PARAM_MARKER)
2602                 {
2603                         start_pos = ++p;
2604                         _tr_parse_sparam(p, p0, tp, spec, ps, in, s);
2605                         t->params->next = tp;
2606                         tp = 0;
2607                         if (p - start_pos != 1)
2608                         {
2609                                 LM_ERR("invalid separator in transformation: "
2610                                                 "%.*s\n", in->len, in->s);
2611                                 goto error;
2612                         }
2613                         while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2614                 }
2615
2616                 if(*p!=TR_RBRACKET)
2617                 {
2618                         LM_ERR("invalid value transformation: %.*s!\n",
2619                                         in->len, in->s);
2620                         goto error;
2621                 }
2622                 goto done;
2623         } else if(name.len==7 && strncasecmp(name.s, "valueat", 7)==0) {
2624                 t->subtype = TR_PL_VALUEAT;
2625                 if(*p!=TR_PARAM_MARKER)
2626                 {
2627                         LM_ERR("invalid name transformation: %.*s\n",
2628                                         in->len, in->s);
2629                         goto error;
2630                 }
2631                 p++;
2632                 _tr_parse_nparam(p, p0, tp, spec, n, sign, in, s)
2633                         t->params = tp;
2634                 tp = 0;
2635                 while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2636
2637                 if(*p==TR_PARAM_MARKER)
2638                 {
2639                         start_pos = ++p;
2640                         _tr_parse_sparam(p, p0, tp, spec, ps, in, s);
2641                         t->params->next = tp;
2642                         tp = 0;
2643                         if (p - start_pos != 1)
2644                         {
2645                                 LM_ERR("invalid separator in transformation: "
2646                                                 "%.*s\n", in->len, in->s);
2647                                 goto error;
2648                         }
2649                         while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2650                 }
2651
2652                 if(*p!=TR_RBRACKET)
2653                 {
2654                         LM_ERR("invalid name transformation: %.*s!\n",
2655                                         in->len, in->s);
2656                         goto error;
2657                 }
2658                 goto done;
2659         } else if(name.len==4 && strncasecmp(name.s, "name", 4)==0) {
2660                 t->subtype = TR_PL_NAME;
2661                 if(*p!=TR_PARAM_MARKER)
2662                 {
2663                         LM_ERR("invalid name transformation: %.*s\n",
2664                                         in->len, in->s);
2665                         goto error;
2666                 }
2667                 p++;
2668                 _tr_parse_nparam(p, p0, tp, spec, n, sign, in, s)
2669                         t->params = tp;
2670                 tp = 0;
2671                 while(is_in_str(p, in) && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2672
2673                 if(*p==TR_PARAM_MARKER)
2674                 {
2675                         start_pos = ++p;
2676                         _tr_parse_sparam(p, p0, tp, spec, ps, in, s);
2677                         t->params->next = tp;
2678                         tp = 0;
2679                         if (p - start_pos != 1)
2680                         {
2681                                 LM_ERR("invalid separator in transformation: "
2682                                                 "%.*s\n", in->len, in->s);
2683                                 goto error;
2684                         }
2685                         while(*p && (*p==' ' || *p=='\t' || *p=='\n')) p++;
2686                 }
2687
2688                 if(*p!=TR_RBRACKET)
2689                 {
2690                         LM_ERR("invalid name transformation: %.*s!\n",
2691                                         in->len, in->s);
2692                         goto error;
2693                 }
2694                 goto done;
2695         } else if(name.len==5 && strncasecmp(name.s, "count", 5)==0) {
2696                 t->subtype = TR_PL_COUNT;
2697                 if(*p==TR_PARAM_MARKER)
2698                 {
2699                         start_pos = ++p;
2700                         _tr_parse_sparam(p, p0, tp, spec, ps, in, s);
2701                         t->params = tp;
2702                         if (tp->type != TR_PARAM_SPEC && p - start_pos != 1)
2703                         {
2704                                 LM_ERR("invalid separator in transformation: "
2705                                                 "%.*s\n", in->len, in->s);