Browse code

Merge commit 'origin/andrei/fixups'

* commit 'origin/andrei/fixups':
avp: comments fix
fixups: added kamailio compatible fixups
fixups: support for PVE & PVS in get_*_fparam()
fixups: fix param function using a param type mask
fixups: generic fixups work now on kamailio pvars
select: comments for parse_select()
avp: minor fixes & comments
sr_module: identing and whitespace

Andrei Pelinescu-Onciul authored on 19/12/2008 13:30:14
Showing 7 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,236 @@
1
+/* 
2
+ * $Id$
3
+ * 
4
+ * Copyright (C) 2008 iptelorg GmbH
5
+ *
6
+ * Permission to use, copy, modify, and distribute this software for any
7
+ * purpose with or without fee is hereby granted, provided that the above
8
+ * copyright notice and this permission notice appear in all copies.
9
+ *
10
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
+ */
18
+/**
19
+ * @file mod_fix.c
20
+ * @brief kamailio compatible fixups
21
+ */
22
+/* 
23
+ * History:
24
+ * --------
25
+ *  2008-11-25  initial version (andrei)
26
+ */
27
+
28
+#include "mod_fix.h"
29
+#include "mem/mem.h"
30
+
31
+
32
+
33
+#if 0
34
+/* TODO: */
35
+int fixup_regexpNL_null(void** param, int param_no); /* not used */
36
+int fixup_regexpNL_none(void** param, int param_no); /* textops */
37
+#endif
38
+
39
+
40
+
41
+#define FREE_FIXUP_FP(suffix, minp, maxp) \
42
+	int fixup_free_##suffix(void** param, int param_no) \
43
+	{ \
44
+		if ((param_no > (maxp)) || (param_no < (minp))) \
45
+			return E_UNSPEC; \
46
+		if (*param){ \
47
+			fparam_free_contents((fparam_t*)*param); \
48
+			pkg_free(*param); \
49
+			*param=0; \
50
+		} \
51
+		return 0; \
52
+	}
53
+
54
+
55
+/** macro for declaring a fixup and the corresponding free_fixup
56
+  * for a function which fixes to fparam_t and expects 2 different types.
57
+  *
58
+  * The result (in *param) will be a fparam_t.
59
+  *
60
+  * @param suffix - function suffix (fixup_ will be pre-pended to it 
61
+  * @param minp - minimum parameter number acceptable
62
+  * @param maxp - maximum parameter number
63
+  * @param no1 -  number of parameters of type1
64
+  * @param type1 - fix_param type for the 1st param
65
+  * @paran type2 - fix_param type for all the other params
66
+  */
67
+#define FIXUP_F2FP(suffix, minp, maxp, no1, type1, type2) \
68
+	int fixup_##suffix (void** param, int param_no) \
69
+	{ \
70
+		if ((param_no > (maxp)) || (param_no <(minp))) \
71
+			return E_UNSPEC; \
72
+		if (param_no <= (no1)){ \
73
+			if (fix_param_types((type1), param)!=0) {\
74
+				ERR("Cannot convert function parameter %d to" #type1 "\n", \
75
+						param_no);\
76
+				return E_UNSPEC; \
77
+			} \
78
+		}else{ \
79
+			if (fix_param_types((type2), param)!=0) {\
80
+				ERR("Cannot convert function parameter %d to" #type2 "\n", \
81
+						param_no); \
82
+				return E_UNSPEC; \
83
+			} \
84
+		}\
85
+		return 0; \
86
+	} \
87
+	FREE_FIXUP_FP(suffix, minp, maxp)
88
+
89
+
90
+/** macro for declaring a fixup and the corresponding free_fixup
91
+  * for a function which fixes directly to the requested type.
92
+  *
93
+  * @see FIXUP_F2FP for the parameters
94
+  * Side effect: declares also some _fp_helper functions
95
+  */
96
+#define FIXUP_F2T(suffix, minp, maxp, no1, type1, type2) \
97
+	FIXUP_F2FP(fp_##suffix, minp, maxp, no1, type1, type2) \
98
+	int fixup_##suffix (void** param, int param_no) \
99
+	{ \
100
+		int ret; \
101
+		if ((ret=fixup_fp_##suffix (param, param_no))!=0) \
102
+			return ret; \
103
+		*param=&((fparam_t*)*param)->v; \
104
+		return 0; \
105
+	} \
106
+	int fixup_free_##suffix (void** param, int param_no) \
107
+	{ \
108
+		void* p; \
109
+		int ret; \
110
+		if (param && *param){ \
111
+			p=*param - (long)&((fparam_t*)0)->v; \
112
+			if ((ret=fixup_free_fp_##suffix(&p, param_no))==0) *param=p; \
113
+			return ret; \
114
+		} \
115
+		return 0; \
116
+	}
117
+
118
+
119
+/** macro for declaring a fixup and the corresponding free_fixup
120
+  * for a function expecting first no1 params as fparamt_t and the
121
+  * rest as direct type.
122
+  *
123
+  * @see FIXUP_F2FP for the parameters with the exception
124
+  * that only the first no1 parameters are converted to 
125
+  * fparamt_t and the rest directly to the correponding type
126
+  *
127
+  * Side effect: declares also some _fpt_helper functions
128
+  */
129
+#define FIXUP_F2FP_T(suffix, minp, maxp, no1, type1, type2) \
130
+	FIXUP_F2FP(fpt_##suffix, minp, maxp, no1, type1, type2) \
131
+	int fixup_##suffix (void** param, int param_no) \
132
+	{ \
133
+		int ret; \
134
+		if ((ret=fixup_fpt_##suffix(param, param_no))!=0) \
135
+			return ret; \
136
+		if (param_no>(no1)) *param=&((fparam_t*)*param)->v; \
137
+		return 0; \
138
+	} \
139
+	int fixup_free_##suffix (void** param, int param_no) \
140
+	{ \
141
+		void* p; \
142
+		int ret; \
143
+		if (param && *param){ \
144
+			p=(param_no>(no1))? *param - (long)&((fparam_t*)0)->v : *param;\
145
+			if ((ret=fixup_free_fpt_##suffix(&p, param_no))==0) *param=0; \
146
+			return ret; \
147
+		} \
148
+		return 0; \
149
+	}
150
+
151
+
152
+/** macro for declaring a fixup which fixes all the paremeters to the same
153
+  * type.
154
+  *
155
+  * @see FIXUP_F2T.
156
+  */
157
+#define FIXUP_F1T(suffix, minp, maxp, type) \
158
+	FIXUP_F2T(suffix, minp, maxp, maxp, type, 0)
159
+
160
+
161
+
162
+FIXUP_F1T(str_null, 1, 1, FPARAM_STR)
163
+FIXUP_F1T(str_str, 1, 2,  FPARAM_STR)
164
+
165
+/* TODO: int can be converted in place, no need for pkg_malloc'ed fparam_t*/
166
+FIXUP_F1T(uint_null, 1, 1, FPARAM_INT)
167
+FIXUP_F1T(uint_uint, 1, 2, FPARAM_INT)
168
+
169
+FIXUP_F1T(regexp_null, 1, 1, FPARAM_REGEX)
170
+
171
+FIXUP_F1T(pvar_null, 1, 1, FPARAM_PVS)
172
+FIXUP_F1T(pvar_pvar, 1, 2, FPARAM_PVS)
173
+
174
+FIXUP_F2T(pvar_str, 1, 2, 1, FPARAM_PVS, FPARAM_STR)
175
+FIXUP_F2T(pvar_str_str, 1, 3, 1, FPARAM_PVS, FPARAM_STR)
176
+
177
+FIXUP_F2FP(igp_null, 1, 1, 1, FPARAM_INT|FPARAM_PVS, 0)
178
+FIXUP_F2FP(igp_igp, 1, 2, 2,  FPARAM_INT|FPARAM_PVS, 0)
179
+
180
+FIXUP_F2FP_T(igp_pvar_pvar, 1, 3, 1, FPARAM_INT|FPARAM_PVS, FPARAM_PVS)
181
+
182
+/** macro for declaring a spve fixup and the corresponding free_fixup
183
+  * for a function expecting first no1 params as fparam converted spve 
184
+  * and the * rest as direct type.
185
+  *
186
+  * @see FIXUP_F2FP for the parameters with the exception
187
+  * that the first no1 parameters are converted to fparam_t from spve
188
+  * and the rest directly to the corresponding type
189
+  *
190
+  * Side effect: declares also some _spvet_helper functions
191
+  */
192
+#define FIXUP_F_SPVE_T(suffix, minp, maxp, no1, type2) \
193
+	FIXUP_F1T(spvet_##suffix, minp, maxp, type2) \
194
+	int fixup_##suffix (void** param, int param_no) \
195
+	{ \
196
+		int ret; \
197
+		char * bkp; \
198
+		fparam_t* fp; \
199
+		bkp=*param; \
200
+		if (param_no<=(no1)){ \
201
+			if ((ret=fix_param_types(FPARAM_PVE, param))<0){ \
202
+				ERR("Cannot convert function parameter %d to" #type2 "\n", \
203
+						param_no);\
204
+				return E_UNSPEC; \
205
+			} else{ \
206
+				fp=(fparam_t*)*param; \
207
+				if ((ret==0) && (fp->v.pve->spec.getf==0)){ \
208
+					fparam_free_contents(fp); \
209
+					pkg_free(fp); \
210
+					*param=bkp; \
211
+					return fix_param_types(FPARAM_STR, param); \
212
+				} else if (ret==1) \
213
+					return fix_param_types(FPARAM_STR, param); \
214
+				return ret; \
215
+			} \
216
+		} else return fixup_spvet_##suffix(param, param_no); \
217
+		return 0; \
218
+	} \
219
+	int fixup_free_##suffix (void** param, int param_no) \
220
+	{ \
221
+		if (param && *param){ \
222
+			if (param_no<=(no1)){ \
223
+				fparam_free_contents((fparam_t*)*param); \
224
+				pkg_free(*param); \
225
+				*param=0; \
226
+			} else \
227
+				return fixup_free_spvet_##suffix(param, param_no); \
228
+		} \
229
+		return 0; \
230
+	}
231
+
232
+
233
+FIXUP_F_SPVE_T(spve_spve, 1, 2, 2, 0)
234
+FIXUP_F_SPVE_T(spve_uint, 1, 2, 2, FPARAM_INT)
235
+FIXUP_F_SPVE_T(spve_str, 1, 2, 2, FPARAM_STR)
236
+
0 237
new file mode 100644
... ...
@@ -0,0 +1,123 @@
1
+/* 
2
+ * $Id$
3
+ * 
4
+ * Copyright (C) 2008 iptelorg GmbH
5
+ *
6
+ * Permission to use, copy, modify, and distribute this software for any
7
+ * purpose with or without fee is hereby granted, provided that the above
8
+ * copyright notice and this permission notice appear in all copies.
9
+ *
10
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
+ */
18
+/**
19
+ * @file mod_fix.h
20
+ * @brief Generic fixup functions for module function parameter.
21
+ * (kamailio compatibility)
22
+ */
23
+
24
+#ifndef _mod_fix_h_
25
+#define _mod_fix_h_
26
+
27
+#include "sr_module.h"
28
+#include "pvar.h"
29
+
30
+#define GPARAM_TYPE_INT		FPARAM_INT
31
+#define GPARAM_TYPE_STR		FPARAM_STR
32
+#define GPARAM_TYPE_PVS		FPARAM_PVS
33
+#define GPARAM_TYPE_PVE		FPARAM_PVE
34
+
35
+/**
36
+ * generic parameter that holds a string, an int, a pseudo-variable
37
+ * or a ser select, avp, or subst.
38
+ * 
39
+ * Note: used only for compatibility with existing kamailio code,
40
+ *  please use fparam_t directly in the future.
41
+ *
42
+ * @see fparam_t
43
+ */
44
+
45
+/* reuse ser fparam_t */
46
+#define gparam_t fparam_t
47
+
48
+typedef gparam_t *gparam_p;
49
+
50
+int fixup_get_svalue(struct sip_msg* msg, gparam_p gp, str *val);
51
+
52
+/** get a string value out of a fparam_t.
53
+  *
54
+  * Note: this macro/function is  for kamailio compatibility
55
+  * (please use get_str_fparam() directly in the future)
56
+  *
57
+  * @param msg  - pointer to the sip message
58
+  * @param fp   - pointer to the fparam_t
59
+  * @param sval - pointer to str, used to store the result
60
+  * @return  0 on success, -1 on error
61
+  */
62
+#define fixup_get_svalue(msg, fp, sval) get_str_fparam(sval, msg, fp)
63
+
64
+/** get an int value out of a fparam_t.
65
+  *
66
+  * Note: this macro/function is  for kamailio compatibility
67
+  * (please use get_int_fparam() directly in the future)
68
+  *
69
+  * @param msg  - pointer to the sip message
70
+  * @param fp   - pointer to the fparam_t
71
+  * @param ival - pointer to str, used to store the result
72
+  * @return  0 on success, -1 on error
73
+  */
74
+#define fixup_get_ivalue(msg, fp, ival) get_int_fparam(ival, msg, fp)
75
+
76
+int fixup_str_null(void** param, int param_no);
77
+int fixup_str_str(void** param, int param_no);
78
+
79
+int fixup_free_str_null(void** param, int param_no);
80
+int fixup_free_str_str(void** param, int param_no);
81
+
82
+int fixup_uint_null(void** param, int param_no);
83
+int fixup_uint_uint(void** param, int param_no);
84
+
85
+
86
+int fixup_regexp_null(void** param, int param_no);
87
+int fixup_free_regexp_null(void** param, int param_no);
88
+int fixup_regexp_none(void** param, int param_no);
89
+int fixup_free_regexp_none(void** param, int param_no);
90
+#if 0
91
+/* not implemened yet */
92
+int fixup_regexpNL_null(void** param, int param_no);
93
+int fixup_regexpNL_none(void** param, int param_no);
94
+#endif
95
+
96
+int fixup_pvar_null(void **param, int param_no);
97
+int fixup_free_pvar_null(void** param, int param_no);
98
+
99
+int fixup_pvar_pvar(void **param, int param_no);
100
+int fixup_free_pvar_pvar(void** param, int param_no);
101
+
102
+int fixup_pvar_str(void** param, int param_no);
103
+int fixup_free_pvar_str(void** param, int param_no);
104
+
105
+int fixup_pvar_str_str(void** param, int param_no);
106
+int fixup_free_pvar_str_str(void** param, int param_no);
107
+
108
+int fixup_igp_igp(void** param, int param_no);
109
+int fixup_igp_null(void** param, int param_no);
110
+int fixup_get_ivalue(struct sip_msg* msg, gparam_p gp, int *val);
111
+
112
+int fixup_igp_pvar_pvar(void** param, int param_no);
113
+int fixup_free_igp_pvar_pvar(void** param, int param_no);
114
+
115
+int fixup_spve_spve(void** param, int param_no);
116
+int fixup_spve_null(void** param, int param_no);
117
+int fixup_spve_uint(void** param, int param_no);
118
+int fixup_spve_str(void** param, int param_no);
119
+
120
+
121
+int fixup_pvar(void **param);
122
+
123
+#endif
... ...
@@ -60,11 +60,30 @@ static select_table_t *select_list = &select_core_table;
60 60
  */
61 61
 int select_level = 0;
62 62
 
63
-/*
63
+/** parse a select identifier (internal version)
64 64
  * Parse select string into select structure s
65
- * moves pointer p to the first unused char
65
+ * moves pointer p to the first unused char.
66
+ *
67
+ * The select identifier must be of the form:
68
+ *   [@] <sel_id> [ '.' <sel_id> ...]
69
+ *   
70
+ * Where 
71
+ *       <sel_id> = <id> |
72
+ *                  <id> '[' <idx> ']'
73
+ *       <id> = [a-zA-Z0-9_]+
74
+ *       <idx> = <number> | <string>
75
+ *       <string> = '"' <ascii> '"' | 
76
+ *                  '\"' <ascii> '\"'
77
+ *
78
+ * Examples:
79
+ *     @to.tag
80
+ *     @hf_value["contact"]
81
+ *     @msg.header["SER-Server-ID"]
82
+ *     @eval.pop[-1]
83
+ *     contact.uri.params.maddr
84
+ *     cfg_get.rtp_proxy.enabled 
66 85
  *
67
- * Returns -1 error
86
+ * @return -1 error
68 87
  *			  p points to the first unconsumed char
69 88
  *          0 success
70 89
  *			  p points to the first unconsumed char
... ...
@@ -148,6 +167,35 @@ error:
148 167
 	return -1;
149 168
 }
150 169
 
170
+
171
+/** parse a select identifier.
172
+ * Parse select string into select structure s and
173
+ * moves pointer p to the first unused char.
174
+ * 
175
+ * The select identifier must be of the form:
176
+ *   [@] <sel_id> [ '.' <sel_id> ...]
177
+ *   
178
+ * Where 
179
+ *       <sel_id> = <id> |
180
+ *                  <id> '[' <idx> ']'
181
+ *       <id> = [a-zA-Z0-9_]+
182
+ *       <idx> = <number>  | '-' <number> | <string>
183
+ *       <string> = '"' <ascii> '"' | 
184
+ *                  '\"' <ascii> '\"'
185
+ *
186
+ * Examples:
187
+ *     @to.tag
188
+ *     @hf_value["contact"]
189
+ *     @msg.header["SER-Server-ID"]
190
+ *     @eval.pop[-1]
191
+ *     contact.uri.params.maddr
192
+ *     cfg_get.rtp_proxy.enabled 
193
+  *
194
+  * @param p - double string (asciiz) pointer, *p is moved to the first char
195
+  *            after the select identifier
196
+  * @param s - the result will be stored here
197
+  * @return  < 0 on error, 0 on success
198
+  */
151 199
 int parse_select (char** p, select_t** s)
152 200
 {
153 201
 	select_t* sel;
... ...
@@ -38,6 +38,7 @@
38 38
  *  2006-02-07  added fix_flag (andrei)
39 39
  *  2008-02-29  store all the reponse callbacks in their own array (andrei)
40 40
  *  2008-11-17  support dual module interface: ser & kamailio (andrei)
41
+ *  2008-11-26  added fparam_free_contents() and fix_param_types (andrei)
41 42
  */
42 43
 
43 44
 
... ...
@@ -897,14 +898,17 @@ int init_modules(void)
897 898
 #endif
898 899
 
899 900
 
900
-action_u_t *fixup_get_param(void **cur_param, int cur_param_no, int required_param_no) {
901
+action_u_t *fixup_get_param(void **cur_param, int cur_param_no,
902
+							int required_param_no)
903
+{
901 904
 	action_u_t *a, a2;
902 905
 	/* cur_param points to a->u.string, get pointer to a */
903 906
 	a = (void*) ((char *)cur_param - ((char *)&a2.u.string-(char *)&a2));
904 907
 	return a + required_param_no - cur_param_no;
905 908
 }
906 909
 
907
-int fixup_get_param_count(void **cur_param, int cur_param_no) {
910
+int fixup_get_param_count(void **cur_param, int cur_param_no)
911
+{
908 912
 	action_u_t *a;
909 913
 	a = fixup_get_param(cur_param, cur_param_no, 0);
910 914
 	if (a)
... ...
@@ -972,125 +976,226 @@ int fix_flag( modparam_t type, void* val,
972 976
  * Common function parameter fixups
973 977
  */
974 978
 
975
-/*
976
- * Generic parameter fixup function which creates
977
- * fparam_t structure. type parameter contains allowed
978
- * parameter types
979
+/** Generic parameter fixup function.
980
+ *  Creates a fparam_t structure.
981
+ *  @param type  contains allowed parameter types
982
+ *  @param param is the parameter that will be fixed-up
979 983
  *
980
- * Returns:
984
+ * @return
981 985
  *    0 on success, 
982 986
  *    1 if the param doesn't match the specified type
983 987
  *    <0 on failure
984 988
  */
985 989
 int fix_param(int type, void** param)
986 990
 {
987
-    fparam_t* p;
988
-    str name, s;
989
-    unsigned int num;
990
-    int err;
991
-
992
-    p = (fparam_t*)pkg_malloc(sizeof(fparam_t));
993
-    if (!p) {
994
-	ERR("No memory left\n");
995
-	return E_OUT_OF_MEM;
996
-    }
997
-    memset(p, 0, sizeof(fparam_t));
998
-    p->orig = *param;
999
-
1000
-    switch(type) {
1001
-    case FPARAM_UNSPEC:
1002
-	ERR("Invalid type value\n");
1003
-	goto error;
1004
-
1005
-    case FPARAM_STRING:
1006
-	p->v.asciiz = *param;
1007
-	break;
1008
-
1009
-    case FPARAM_STR:
1010
-	p->v.str.s = (char*)*param;
1011
-	p->v.str.len = strlen(p->v.str.s);
1012
-	break;
1013
-
1014
-    case FPARAM_INT:
1015
-	s.s = (char*)*param;
1016
-	s.len = strlen(s.s);
1017
-	err = str2int(&s, &num);
1018
-	if (err == 0) {
1019
-	    p->v.i = (int)num;
1020
-	} else {
1021
-	    /* Not a number */
1022
-	    pkg_free(p);
1023
-	    return 1;
1024
-	}
1025
-	break;
991
+	fparam_t* p;
992
+	str name, s;
993
+	unsigned int num;
994
+	int err;
1026 995
 
1027
-    case FPARAM_REGEX:
1028
-	if ((p->v.regex = pkg_malloc(sizeof(regex_t))) == 0) {
1029
-	    ERR("No memory left\n");
1030
-	    goto error;
1031
-	}
1032
-	if (regcomp(p->v.regex, *param, REG_EXTENDED|REG_ICASE|REG_NEWLINE)) {
1033
-	    pkg_free(p->v.regex);
1034
-	    ERR("Bad regular expression '%s'\n", (char*)*param);
1035
-	    goto error;
996
+	p = (fparam_t*)pkg_malloc(sizeof(fparam_t));
997
+	if (!p) {
998
+		ERR("No memory left\n");
999
+		return E_OUT_OF_MEM;
1036 1000
 	}
1037
-	break;
1038
-
1039
-    case FPARAM_AVP:
1040
-	name.s = (char*)*param;
1041
-	name.len = strlen(name.s);
1042
-	trim(&name);
1043
-	if (!name.len || name.s[0] != '$') {
1044
-	    /* Not an AVP identifier */
1045
-	    pkg_free(p);
1046
-	    return 1;
1001
+	memset(p, 0, sizeof(fparam_t));
1002
+	p->orig = *param;
1003
+	
1004
+	switch(type) {
1005
+		case FPARAM_UNSPEC:
1006
+			ERR("Invalid type value\n");
1007
+			goto error;
1008
+		case FPARAM_STRING:
1009
+			p->v.asciiz = *param;
1010
+		
1011
+		case FPARAM_STR:
1012
+			p->v.str.s = (char*)*param;
1013
+			p->v.str.len = strlen(p->v.str.s);
1014
+			break;
1015
+		case FPARAM_INT:
1016
+			s.s = (char*)*param;
1017
+			s.len = strlen(s.s);
1018
+			err = str2int(&s, &num);
1019
+			if (err == 0) {
1020
+				p->v.i = (int)num;
1021
+			} else {
1022
+				/* Not a number */
1023
+				pkg_free(p);
1024
+				return 1;
1025
+			}
1026
+			break;
1027
+		case FPARAM_REGEX:
1028
+			if ((p->v.regex = pkg_malloc(sizeof(regex_t))) == 0) {
1029
+				ERR("No memory left\n");
1030
+			goto error;
1031
+			}
1032
+			if (regcomp(p->v.regex, *param,
1033
+						REG_EXTENDED|REG_ICASE|REG_NEWLINE)) {
1034
+				pkg_free(p->v.regex);
1035
+				p->v.regex=0;
1036
+				ERR("Bad regular expression '%s'\n", (char*)*param);
1037
+				goto error;
1038
+			}
1039
+			break;
1040
+		case FPARAM_AVP:
1041
+			name.s = (char*)*param;
1042
+			name.len = strlen(name.s);
1043
+			trim(&name);
1044
+			if (!name.len || name.s[0] != '$') {
1045
+				/* Not an AVP identifier */
1046
+				pkg_free(p);
1047
+				return 1;
1048
+			}
1049
+			name.s++;
1050
+			name.len--;
1051
+			if (parse_avp_ident(&name, &p->v.avp) < 0) {
1052
+				ERR("Error while parsing attribute name\n");
1053
+				goto error;
1054
+			}
1055
+			break;
1056
+		case FPARAM_SELECT:
1057
+			name.s = (char*)*param;
1058
+			name.len = strlen(name.s);
1059
+			trim(&name);
1060
+			if (!name.len || name.s[0] != '@') {
1061
+				/* Not a select identifier */
1062
+				pkg_free(p);
1063
+				return 1;
1064
+			}
1065
+			if (parse_select(&name.s, &p->v.select) < 0) {
1066
+				ERR("Error while parsing select identifier\n");
1067
+				goto error;
1068
+			}
1069
+			break;
1070
+		case FPARAM_SUBST:
1071
+			s.s = *param;
1072
+			s.len = strlen(s.s);
1073
+			p->v.subst = subst_parser(&s);
1074
+			if (!p->v.subst) {
1075
+				ERR("Error while parsing regex substitution\n");
1076
+				goto error;
1077
+			}
1078
+			break;
1079
+		case FPARAM_PVS:
1080
+			name.s = (char*)*param;
1081
+			name.len = strlen(name.s);
1082
+			trim(&name);
1083
+			if (!name.len || name.s[0] != '$'){
1084
+				/* not a pvs identifier */
1085
+				pkg_free(p);
1086
+				return 1;
1087
+			}
1088
+			p->v.pvs=pkg_malloc(sizeof(pv_spec_t));
1089
+			if (p->v.pvs==0){
1090
+				ERR("out of memory while parsing pv_spec_t\n");
1091
+				goto error;
1092
+			}
1093
+			if (pv_parse_spec(&name, p->v.pvs)==0){
1094
+				ERR("unsupported user field indentifier \"%.*s\"\n",
1095
+						name.len, name.s);
1096
+				pkg_free(p->v.pvs);
1097
+				p->v.pvs=0;
1098
+				goto error;
1099
+			}
1100
+			break;
1101
+		case FPARAM_PVE:
1102
+			name.s = (char*)*param;
1103
+			name.len = strlen(name.s);
1104
+			if (pv_parse_format(&name, &p->v.pve)<0){
1105
+				ERR("bad PVE format: \"%.*s\"\n", name.len, name.s);
1106
+				goto error;
1107
+			}
1108
+			break;
1047 1109
 	}
1048
-	name.s++;
1049
-	name.len--;
1110
+	
1111
+	p->type = type;
1112
+	*param = (void*)p;
1113
+	return 0;
1114
+	
1115
+error:
1116
+	pkg_free(p);
1117
+	return E_UNSPEC;
1118
+}
1050 1119
 
1051
-	if (parse_avp_ident(&name, &p->v.avp) < 0) {
1052
-	    ERR("Error while parsing attribute name\n");
1053
-	    goto error;
1054
-	}
1055
-	break;
1056
-
1057
-    case FPARAM_SELECT:
1058
-	name.s = (char*)*param;
1059
-	name.len = strlen(name.s);
1060
-	trim(&name);
1061
-	if (!name.len || name.s[0] != '@') {
1062
-	    /* Not a select identifier */
1063
-	    pkg_free(p);
1064
-	    return 1;
1065
-	}
1066 1120
 
1067
-	if (parse_select(&name.s, &p->v.select) < 0) {
1068
-	    ERR("Error while parsing select identifier\n");
1069
-	    goto error;
1070
-	}
1071
-	break;
1072
-
1073
-    case FPARAM_SUBST:
1074
-	s.s = *param;
1075
-	s.len = strlen(s.s);
1076
-	p->v.subst = subst_parser(&s);
1077
-	if (!p->v.subst) {
1078
-	    ERR("Error while parsing regex substitution\n");
1079
-	    goto error;
1121
+
1122
+/** fparam_t free function.
1123
+ *  Frees the "content" of a fparam, but not the fparam itself.
1124
+ *  Assumes pkg_malloc'ed content.
1125
+ *  @param fp -  fparam to be freed
1126
+ *
1127
+ */
1128
+void fparam_free_contents(fparam_t* fp)
1129
+{
1130
+
1131
+	if (fp==0)
1132
+		return;
1133
+	switch(fp->type) {
1134
+		case FPARAM_UNSPEC:
1135
+		case FPARAM_STRING: /* asciiz string, not str */
1136
+		case FPARAM_INT:
1137
+		case FPARAM_STR:
1138
+			/* nothing to do */
1139
+			return;
1140
+		case FPARAM_REGEX:
1141
+			if (fp->v.regex){
1142
+				regfree(fp->v.regex);
1143
+				pkg_free(fp->v.regex);
1144
+				fp->v.regex=0;
1145
+			}
1146
+			break;
1147
+		case FPARAM_AVP:
1148
+			free_avp_name(&fp->v.avp.flags, &fp->v.avp.name);
1149
+			break;
1150
+		case FPARAM_SELECT:
1151
+			if (fp->v.select){
1152
+				free_select(fp->v.select);
1153
+				fp->v.select=0;
1154
+			}
1155
+			break;
1156
+		case FPARAM_SUBST:
1157
+			if (fp->v.subst){
1158
+				subst_expr_free(fp->v.subst);
1159
+				fp->v.subst=0;
1160
+			}
1161
+			break;
1162
+		case FPARAM_PVS:
1163
+			if (fp->v.pvs){
1164
+				pv_spec_free(fp->v.pvs);
1165
+				fp->v.pvs=0;
1166
+			}
1167
+			break;
1168
+		case FPARAM_PVE:
1169
+			if (fp->v.pve){
1170
+				pv_elem_free_all(fp->v.pve);
1171
+				fp->v.pve=0;
1172
+			}
1173
+			break;
1080 1174
 	}
1081
-	break;
1082
-    }
1175
+}
1176
+
1083 1177
 
1084
-    p->type = type;
1085
-    *param = (void*)p;
1086
-    return 0;
1087 1178
 
1088
- error:
1089
-    pkg_free(p);
1090
-    return E_UNSPEC;
1179
+/** fix a param to one of the given types (mask).
1180
+  *
1181
+  * @param types - bitmap of the allowed types (e.g. FPARAM_INT|FPARAM_STR)
1182
+  * @param param - value/result
1183
+  * @return - 0 on success, -1 on error, 1 if param doesn't
1184
+  *           match any of the types
1185
+  */
1186
+int fix_param_types(int types, void** param)
1187
+{
1188
+	int ret;
1189
+	int t;
1190
+	
1191
+	for (t=types & ~(types-1); types; types&=(types-1), t=types & ~(types-1)){
1192
+		if ((ret=fix_param(t, param))<=0) return ret;
1193
+	}
1194
+	return E_UNSPEC;
1091 1195
 }
1092 1196
 
1093 1197
 
1198
+
1094 1199
 /*
1095 1200
  * Fixup variable string, the parameter can be
1096 1201
  * AVP, SELECT, or ordinary string. AVP and select
... ...
@@ -1102,26 +1207,27 @@ int fix_param(int type, void** param)
1102 1207
  */
1103 1208
 int fixup_var_str_12(void** param, int param_no)
1104 1209
 {
1105
-    int ret;
1106
-    if ((ret = fix_param(FPARAM_AVP, param)) <= 0) return ret;
1107
-    if ((ret = fix_param(FPARAM_SELECT, param)) <= 0) return ret;
1108
-    if ((ret = fix_param(FPARAM_STR, param)) <= 0) return ret;
1109
-    ERR("Error while fixing parameter, AVP, SELECT, and str conversions failed\n");
1110
-    return -1;
1210
+	int ret;
1211
+	if ((ret = fix_param(FPARAM_AVP, param)) <= 0) return ret;
1212
+	if ((ret = fix_param(FPARAM_SELECT, param)) <= 0) return ret;
1213
+	if ((ret = fix_param(FPARAM_STR, param)) <= 0) return ret;
1214
+	ERR("Error while fixing parameter, AVP, SELECT, and str conversions"
1215
+			" failed\n");
1216
+	return -1;
1111 1217
 }
1112 1218
 
1113 1219
 /* Same as fixup_var_str_12 but applies to the 1st parameter only */
1114 1220
 int fixup_var_str_1(void** param, int param_no)
1115 1221
 {
1116
-    if (param_no == 1) return fixup_var_str_12(param, param_no);
1117
-    else return 0;
1222
+	if (param_no == 1) return fixup_var_str_12(param, param_no);
1223
+	else return 0;
1118 1224
 }
1119 1225
 
1120 1226
 /* Same as fixup_var_str_12 but applies to the 2nd parameter only */
1121 1227
 int fixup_var_str_2(void** param, int param_no)
1122 1228
 {
1123
-    if (param_no == 2) return fixup_var_str_12(param, param_no);
1124
-    else return 0;
1229
+	if (param_no == 2) return fixup_var_str_12(param, param_no);
1230
+	else return 0;
1125 1231
 }
1126 1232
 
1127 1233
 
... ...
@@ -1136,26 +1242,27 @@ int fixup_var_str_2(void** param, int param_no)
1136 1242
  */
1137 1243
 int fixup_var_int_12(void** param, int param_no)
1138 1244
 {
1139
-    int ret;
1140
-    if ((ret = fix_param(FPARAM_AVP, param)) <= 0) return ret;
1141
-    if ((ret = fix_param(FPARAM_SELECT, param)) <= 0) return ret;
1142
-    if ((ret = fix_param(FPARAM_INT, param)) <= 0) return ret;
1143
-    ERR("Error while fixing parameter, AVP, SELECT, and int conversions failed\n");
1144
-    return -1;
1245
+	int ret;
1246
+	if ((ret = fix_param(FPARAM_AVP, param)) <= 0) return ret;
1247
+	if ((ret = fix_param(FPARAM_SELECT, param)) <= 0) return ret;
1248
+	if ((ret = fix_param(FPARAM_INT, param)) <= 0) return ret;
1249
+	ERR("Error while fixing parameter, AVP, SELECT, and int conversions"
1250
+			" failed\n");
1251
+	return -1;
1145 1252
 }
1146 1253
 
1147 1254
 /* Same as fixup_var_int_12 but applies to the 1st parameter only */
1148 1255
 int fixup_var_int_1(void** param, int param_no)
1149 1256
 {
1150
-    if (param_no == 1) return fixup_var_int_12(param, param_no);
1151
-    else return 0;
1257
+	if (param_no == 1) return fixup_var_int_12(param, param_no);
1258
+	else return 0;
1152 1259
 }
1153 1260
 
1154 1261
 /* Same as fixup_var_int_12 but applies to the 2nd parameter only */
1155 1262
 int fixup_var_int_2(void** param, int param_no)
1156 1263
 {
1157
-    if (param_no == 2) return fixup_var_int_12(param, param_no);
1158
-    else return 0;
1264
+	if (param_no == 2) return fixup_var_int_12(param, param_no);
1265
+	else return 0;
1159 1266
 }
1160 1267
 
1161 1268
 
... ...
@@ -1165,25 +1272,25 @@ int fixup_var_int_2(void** param, int param_no)
1165 1272
  */
1166 1273
 int fixup_regex_12(void** param, int param_no)
1167 1274
 {
1168
-    int ret;
1275
+	int ret;
1169 1276
 
1170
-    if ((ret = fix_param(FPARAM_REGEX, param)) <= 0) return ret;
1171
-    ERR("Error while compiling regex in function parameter\n");
1172
-    return -1;
1277
+	if ((ret = fix_param(FPARAM_REGEX, param)) <= 0) return ret;
1278
+	ERR("Error while compiling regex in function parameter\n");
1279
+	return -1;
1173 1280
 }
1174 1281
 
1175 1282
 /* Same as fixup_regex_12 but applies to the 1st parameter only */
1176 1283
 int fixup_regex_1(void** param, int param_no)
1177 1284
 {
1178
-    if (param_no == 1) return fixup_regex_12(param, param_no);
1179
-    else return 0;
1285
+	if (param_no == 1) return fixup_regex_12(param, param_no);
1286
+	else return 0;
1180 1287
 }
1181 1288
 
1182 1289
 /* Same as fixup_regex_12 but applies to the 2nd parameter only */
1183 1290
 int fixup_regex_2(void** param, int param_no)
1184 1291
 {
1185
-    if (param_no == 2) return fixup_regex_12(param, param_no);
1186
-    else return 0;
1292
+	if (param_no == 2) return fixup_regex_12(param, param_no);
1293
+	else return 0;
1187 1294
 }
1188 1295
 
1189 1296
 /*
... ...
@@ -1191,26 +1298,26 @@ int fixup_regex_2(void** param, int param_no)
1191 1298
  */
1192 1299
 int fixup_int_12(void** param, int param_no)
1193 1300
 {
1194
-    int ret;
1301
+	int ret;
1195 1302
 
1196
-    if ((ret = fix_param(FPARAM_INT, param)) <= 0) return ret;
1197
-    ERR("Cannot function parameter to integer\n");
1198
-    return -1;
1303
+	if ((ret = fix_param(FPARAM_INT, param)) <= 0) return ret;
1304
+	ERR("Cannot function parameter to integer\n");
1305
+	return -1;
1199 1306
 
1200 1307
 }
1201 1308
 
1202 1309
 /* Same as fixup_int_12 but applies to the 1st parameter only */
1203 1310
 int fixup_int_1(void** param, int param_no)
1204 1311
 {
1205
-    if (param_no == 1) return fixup_int_12(param, param_no);
1206
-    else return 0;
1312
+	if (param_no == 1) return fixup_int_12(param, param_no);
1313
+	else return 0;
1207 1314
 }
1208 1315
 
1209 1316
 /* Same as fixup_int_12 but applies to the 2nd parameter only */
1210 1317
 int fixup_int_2(void** param, int param_no)
1211 1318
 {
1212
-    if (param_no == 2) return fixup_int_12(param, param_no);
1213
-    else return 0;
1319
+	if (param_no == 2) return fixup_int_12(param, param_no);
1320
+	else return 0;
1214 1321
 }
1215 1322
 
1216 1323
 /*
... ...
@@ -1219,130 +1326,155 @@ int fixup_int_2(void** param, int param_no)
1219 1326
  */
1220 1327
 int fixup_str_12(void** param, int param_no)
1221 1328
 {
1222
-    int ret;
1329
+	int ret;
1223 1330
 
1224
-    if ((ret = fix_param(FPARAM_STR, param)) <= 0) return ret;
1225
-    ERR("Cannot function parameter to string\n");
1226
-    return -1;
1331
+	if ((ret = fix_param(FPARAM_STR, param)) <= 0) return ret;
1332
+	ERR("Cannot function parameter to string\n");
1333
+	return -1;
1227 1334
 }
1228 1335
 
1229 1336
 /* Same as fixup_str_12 but applies to the 1st parameter only */
1230 1337
 int fixup_str_1(void** param, int param_no)
1231 1338
 {
1232
-    if (param_no == 1) return fixup_str_12(param, param_no);
1233
-    else return 0;
1339
+	if (param_no == 1) return fixup_str_12(param, param_no);
1340
+	else return 0;
1234 1341
 }
1235 1342
 
1236 1343
 /* Same as fixup_str_12 but applies to the 2nd parameter only */
1237 1344
 int fixup_str_2(void** param, int param_no)
1238 1345
 {
1239
-    if (param_no == 2) return fixup_str_12(param, param_no);
1240
-    else return 0;
1346
+	if (param_no == 2) return fixup_str_12(param, param_no);
1347
+	else return 0;
1241 1348
 }
1242 1349
 
1243 1350
 
1244
-/*
1245
- * Get the function parameter value as string
1246
- * Return values:  0 - Success
1247
- *                -1 - Cannot get value
1351
+/** Get the function parameter value as string.
1352
+ *  @return  0 - Success
1353
+ *          -1 - Cannot get value
1248 1354
  */
1249 1355
 int get_str_fparam(str* dst, struct sip_msg* msg, fparam_t* param)
1250 1356
 {
1251
-    int_str val;
1252
-    int ret;
1253
-    avp_t* avp;
1254
-
1255
-    switch(param->type) {
1256
-    case FPARAM_REGEX:
1257
-    case FPARAM_UNSPEC:
1258
-    case FPARAM_INT:
1259
-	return -1;
1260
-
1261
-    case FPARAM_STRING:
1262
-	dst->s = param->v.asciiz;
1263
-	dst->len = strlen(param->v.asciiz);
1264
-	break;
1265
-
1266
-    case FPARAM_STR:
1267
-	*dst = param->v.str;
1268
-	break;
1269
-
1270
-    case FPARAM_AVP:
1271
-	avp = search_first_avp(param->v.avp.flags, param->v.avp.name, &val, 0);
1272
-	if (!avp) {
1273
-	    DBG("Could not find AVP from function parameter '%s'\n", param->orig);
1274
-	    return -1;
1275
-	}
1276
-	if (avp->flags & AVP_VAL_STR) {
1277
-	    *dst = val.s;
1278
-	} else {
1279
-		 /* The caller does not know of what type the AVP will be so
1280
-		  * convert int AVPs into string here
1281
-		  */
1282
-	    dst->s = int2str(val.n, &dst->len);
1357
+	int_str val;
1358
+	int ret;
1359
+	avp_t* avp;
1360
+	pv_value_t pv_val;
1361
+	static char pve_buf[256]; /* ugly hack needed for PVE */
1362
+	
1363
+	switch(param->type) {
1364
+		case FPARAM_REGEX:
1365
+		case FPARAM_UNSPEC:
1366
+		case FPARAM_INT:
1367
+			return -1;
1368
+		case FPARAM_STRING:
1369
+			dst->s = param->v.asciiz;
1370
+			dst->len = strlen(param->v.asciiz);
1371
+			break;
1372
+		case FPARAM_STR:
1373
+			*dst = param->v.str;
1374
+			break;
1375
+		case FPARAM_AVP:
1376
+			avp = search_first_avp(param->v.avp.flags, param->v.avp.name,
1377
+									&val, 0);
1378
+			if (unlikely(!avp)) {
1379
+				DBG("Could not find AVP from function parameter '%s'\n",
1380
+						param->orig);
1381
+				return -1;
1382
+			}
1383
+			if (likely(avp->flags & AVP_VAL_STR)) {
1384
+				*dst = val.s;
1385
+			} else {
1386
+		 		/* The caller does not know of what type the AVP will be so
1387
+				 * convert int AVPs into string here
1388
+				 */
1389
+				dst->s = int2str(val.n, &dst->len);
1390
+			}
1391
+			break;
1392
+		case FPARAM_SELECT:
1393
+			ret = run_select(dst, param->v.select, msg);
1394
+			if (unlikely(ret < 0 || ret > 0)) return -1;
1395
+			break;
1396
+		case FPARAM_PVS:
1397
+			if (likely((pv_get_spec_value(msg, param->v.pvs, &pv_val)==0) &&
1398
+					   ((pv_val.flags&(PV_VAL_NULL|PV_VAL_STR))==PV_VAL_STR))){
1399
+					*dst=pv_val.rs;
1400
+			}else{
1401
+				ERR("Could not convert PV to str\n");
1402
+				return -1;
1403
+			}
1404
+			break;
1405
+		case FPARAM_PVE:
1406
+			dst->len=sizeof(pve_buf);
1407
+			if (unlikely(pv_printf(msg, param->v.pve, pve_buf, &dst->len)!=0)){
1408
+				ERR("Could not convert the PV-formated string to str\n");
1409
+				dst->len=0;
1410
+				return -1;
1411
+			};
1412
+			dst->s=pve_buf;
1413
+			break;
1283 1414
 	}
1284
-	break;
1285
-
1286
-    case FPARAM_SELECT:
1287
-	ret = run_select(dst, param->v.select, msg);
1288
-	if (ret < 0 || ret > 0) return -1;
1289
-	break;
1290
-    }
1291
-
1292
-    return 0;
1415
+	return 0;
1293 1416
 }
1294 1417
 
1295 1418
 
1296
-/*
1297
- * Get the function parameter value as integer
1298
- * Return values:  0 - Success
1299
- *                -1 - Cannot get value
1419
+/** Get the function parameter value as integer.
1420
+ *  @return  0 - Success
1421
+ *          -1 - Cannot get value
1300 1422
  */
1301 1423
 int get_int_fparam(int* dst, struct sip_msg* msg, fparam_t* param)
1302 1424
 {
1303
-    int_str val;
1304
-    int ret;
1305
-    avp_t* avp;
1306
-    str tmp;
1307
-
1308
-    switch(param->type) {
1309
-    case FPARAM_INT:
1310
-	*dst = param->v.i;
1311
-	return 0;
1312
-
1313
-    case FPARAM_REGEX:
1314
-    case FPARAM_UNSPEC:
1315
-    case FPARAM_STRING:
1316
-    case FPARAM_STR:
1317
-	return -1;
1425
+	int_str val;
1426
+	int ret;
1427
+	avp_t* avp;
1428
+	str tmp;
1429
+	pv_value_t pv_val;
1318 1430
 
1319
-    case FPARAM_AVP:
1320
-	avp = search_first_avp(param->v.avp.flags, param->v.avp.name, &val, 0);
1321
-	if (!avp) {
1322
-	    DBG("Could not find AVP from function parameter '%s'\n", param->orig);
1323
-	    return -1;
1324
-	}
1325
-	if (avp->flags & AVP_VAL_STR) {
1326
-	    if (str2int(&val.s, (unsigned int*)dst) < 0) {
1327
-		ERR("Could not convert AVP string value to int\n");
1328
-		return -1;
1329
-	    }
1330
-	} else {
1331
-	    *dst = val.n;
1332
-	}
1333
-	break;
1334
-
1335
-    case FPARAM_SELECT:
1336
-	ret = run_select(&tmp, param->v.select, msg);
1337
-	if (ret < 0 || ret > 0) return -1;
1338
-	if (str2int(&tmp, (unsigned int*)dst) < 0) {
1339
-	    ERR("Could not convert select result to int\n");
1340
-	    return -1;
1431
+	switch(param->type) {
1432
+		case FPARAM_INT:
1433
+			*dst = param->v.i;
1434
+			return 0;
1435
+		case FPARAM_REGEX:
1436
+		case FPARAM_UNSPEC:
1437
+		case FPARAM_STRING:
1438
+		case FPARAM_STR:
1439
+			return -1;
1440
+		case FPARAM_AVP:
1441
+			avp = search_first_avp(param->v.avp.flags, param->v.avp.name,
1442
+									&val, 0);
1443
+			if (unlikely(!avp)) {
1444
+				DBG("Could not find AVP from function parameter '%s'\n",
1445
+						param->orig);
1446
+				return -1;
1447
+			}
1448
+			if (avp->flags & AVP_VAL_STR) {
1449
+				if (str2int(&val.s, (unsigned int*)dst) < 0) {
1450
+					ERR("Could not convert AVP string value to int\n");
1451
+					return -1;
1452
+				}
1453
+			} else {
1454
+				*dst = val.n;
1455
+			}
1456
+			break;
1457
+		case FPARAM_SELECT:
1458
+			ret = run_select(&tmp, param->v.select, msg);
1459
+			if (unlikely(ret < 0 || ret > 0)) return -1;
1460
+			if (unlikely(str2int(&tmp, (unsigned int*)dst) < 0)) {
1461
+				ERR("Could not convert select result to int\n");
1462
+				return -1;
1463
+			}
1464
+			break;
1465
+		case FPARAM_PVS:
1466
+			if (likely((pv_get_spec_value(msg, param->v.pvs, &pv_val)==0) &&
1467
+					   ((pv_val.flags&(PV_VAL_NULL|PV_VAL_INT))==PV_VAL_INT))){
1468
+					*dst=pv_val.ri;
1469
+			}else{
1470
+				ERR("Could not convert PV to int\n");
1471
+				return -1;
1472
+			}
1473
+			break;
1474
+		case FPARAM_PVE:
1475
+			return -1;
1341 1476
 	}
1342
-	break;
1343
-    }
1344
-
1345
-    return 0;
1477
+	return 0;
1346 1478
 }
1347 1479
 
1348 1480
 /**
... ...
@@ -1355,7 +1487,6 @@ int get_regex_fparam(regex_t *dst, struct sip_msg* msg, fparam_t* param)
1355 1487
 		case FPARAM_REGEX:
1356 1488
 			*dst = *param->v.regex;
1357 1489
 			return 0;
1358
-
1359 1490
 		default:
1360 1491
 			ERR("unexpected parameter type (%d), instead of regexp.\n", 
1361 1492
 					param->type);
... ...
@@ -46,6 +46,7 @@
46 46
  *              dual module interface support: ser & kamailio (andrei)
47 47
  *  2008-11-18  prototypes for various fixed parameters numbers module
48 48
  *               functions (3, 4, 5 & 6) and variable parameters (andrei)
49
+ *  2008-11-26  added fparam_free_contents() and fix_param_types (andrei)
49 50
  */
50 51
 
51 52
 /*!
... ...
@@ -234,17 +235,23 @@ struct param_export_ {
234 235
 };
235 236
 
236 237
 
238
+
239
+/** allowed parameter types.
240
+  * the types that cannot be deduced from the string, should
241
+  * be at the end (e.g. FPARAM_STR), to allow fallback 
242
+  * (e.g. fix_param_types(FPARAM_AVP|FPARAM_SELECT|FPARAM_STR, param))
243
+  */
237 244
 enum {
238 245
 	FPARAM_UNSPEC = 0,
239
-	FPARAM_STRING = (1 << 0),
240
-	FPARAM_STR    = (1 << 1),
241
-	FPARAM_INT    = (1 << 2),
242
-	FPARAM_REGEX  = (1 << 3),
243
-	FPARAM_AVP    = (1 << 5),
244
-	FPARAM_SELECT = (1 << 6),
245
-	FPARAM_SUBST  = (1 << 7),
246
-	FPARAM_PVS    = (1 << 8),
247
-	FPARAM_PVE    = (1 << 9)
246
+	FPARAM_INT    = (1 << 0),
247
+	FPARAM_REGEX  = (1 << 1),
248
+	FPARAM_AVP    = (1 << 2),
249
+	FPARAM_SELECT = (1 << 3),
250
+	FPARAM_SUBST  = (1 << 4),
251
+	FPARAM_PVS    = (1 << 5),
252
+	FPARAM_PVE    = (1 << 6),
253
+	FPARAM_STRING = (1 << 7),
254
+	FPARAM_STR    = (1 << 8)
248 255
 };
249 256
 
250 257
 /*
... ...
@@ -261,8 +268,8 @@ typedef struct fparam {
261 268
 		avp_ident_t avp;          /* AVP identifier */
262 269
 		select_t* select;         /* select structure */ 
263 270
 		struct subst_expr* subst; /* Regex substitution */
264
-		struct pv_spec_t* pvs;    /* kamailo pseudo-vars */
265
-		struct pv_elem_t* pve;    /* kamailo pseudo-vars */
271
+		pv_spec_t* pvs;    /* kamailo pseudo-vars */
272
+		pv_elem_t* pve;    /* kamailo pseudo-vars in a string */
266 273
 	} v;
267 274
 } fparam_t;
268 275
 
... ...
@@ -417,6 +424,11 @@ int fix_flag( modparam_t type, void* val,
417 424
  * parameter types
418 425
  */
419 426
 int fix_param(int type, void** param);
427
+void fparam_free_contents(fparam_t* fp);
428
+
429
+/** fix a param to one of the given types (mask).
430
+  */
431
+int fix_param_types(int types, void** param);
420 432
 
421 433
 /*
422 434
  * Fixup variable string, the parameter can be
... ...
@@ -831,6 +831,39 @@ int parse_avp_name( str *name, int *type, int_str *avp_name, int *index)
831 831
 	return ret;
832 832
 }
833 833
 
834
+
835
+/** parse an avp indentifier.
836
+ *
837
+ * Parses the following avp indentifier forms:
838
+ *       - "i:<number>"  - old form, deprecated  (e.g. i:42)
839
+ *       - "s:<string>"  - old form, deprecated  (e.g. s:foo)
840
+ *       - "<track>.<name>"                      (e.g.: f.bar)
841
+ *       - "<track>.<name>[<index>]"             (e.g.: f.bar[1])
842
+ *       - "<track><class>.<name>"               (e.g:  tu.bar)
843
+ *       - "<track><class>.<name>[<index>]"      (e.g:  fd.bar[2])
844
+ *       - "<string>"                            (e.g.: foo)
845
+ * Where:
846
+ *          <string> = ascii string
847
+ *          <id>   = ascii string w/o '[', ']', '.' and '/'
848
+ *          <name> = <id> | '/' regex '/'
849
+ *                   (Note: regex use is deprecated)
850
+ *          <track> = 'f' | 't'
851
+ *                   (from or to)
852
+ *          <class> = 'r' | 'u' | 'd' | 'g'
853
+ *                    (uri, user, domain or global)
854
+ *          <index> = <number> | '-' <number> | ''
855
+ *                    (the avp index, if missing it means AVP_INDEX_ALL, but
856
+ *                     it's use is deprecated)
857
+ * More examples:
858
+ *       "fr.bar[1]"  - from track, uri class, avp "bar", the value 1.
859
+ *       "tu./^foo/"  - to track,  user class, all avps for which the name
860
+ *                      starts with foo (note RE in avp names are deprecated).
861
+ *        "t.did"     - to track, "did" avp
862
+ *
863
+ * @param name  - avp identifier
864
+ * @param *attr - the result will be stored here
865
+ * @return 0 on success, -1 on error
866
+ */
834 867
 int parse_avp_ident( str *name, avp_ident_t* attr)
835 868
 {
836 869
 	unsigned int id;
... ...
@@ -960,6 +993,7 @@ int parse_avp_ident( str *name, avp_ident_t* attr)
960 993
 			name->s[name->len-1]=0;
961 994
 			if (regcomp(attr->name.re, name->s+1, REG_EXTENDED|REG_NOSUB|REG_ICASE)) {
962 995
 				pkg_free(attr->name.re);
996
+				attr->name.re=0;
963 997
 				name->s[name->len-1] = '/';
964 998
 				goto error;
965 999
 			}
... ...
@@ -1003,10 +1037,13 @@ int parse_avp_spec( str *name, int *type, int_str *avp_name, int *index)
1003 1037
 	}
1004 1038
 }
1005 1039
 
1006
-void free_avp_name( int *type, int_str *avp_name)
1040
+void free_avp_name(avp_flags_t *type, int_str *avp_name)
1007 1041
 {
1008
-	if ((*type & AVP_NAME_RE) && (avp_name->re))
1042
+	if ((*type & AVP_NAME_RE) && (avp_name->re)){
1043
+		regfree(avp_name->re);
1009 1044
 		pkg_free(avp_name->re);
1045
+		avp_name->re=0;
1046
+	}
1010 1047
 }
1011 1048
 
1012 1049
 int add_avp_galias_str(char *alias_definition)
... ...
@@ -203,7 +203,7 @@ int add_avp_galias(str *alias, int type, int_str avp_name);
203 203
 int parse_avp_ident( str *name, avp_ident_t* attr);
204 204
 int parse_avp_name( str *name, int *type, int_str *avp_name, int *index);
205 205
 int parse_avp_spec( str *name, int *type, int_str *avp_name, int *index);
206
-void free_avp_name( int *type, int_str *avp_name);
206
+void free_avp_name( avp_flags_t *type, int_str *avp_name);
207 207
 
208 208
 /* AVP flags functions */
209 209
 #define MAX_AVPFLAG  ((unsigned int)( sizeof(avp_flags_t) * CHAR_BIT - 1 - AVP_CUSTOM_FLAGS))