Browse code

phonenum: new param resid to register result container ids

- allow use in KEMI scripting by pre-registering container result id via
modparam

Daniel-Constantin Mierla authored on 02/09/2019 11:41:03
Showing 1 changed files
... ...
@@ -111,6 +111,13 @@ sr_phonenum_item_t *sr_phonenum_add_item(str *name)
111 111
 	return it;
112 112
 }
113 113
 
114
+int sr_phonenum_add_resid(str *rname)
115
+{
116
+	if(sr_phonenum_add_item(rname)==NULL) {
117
+		return -1;
118
+	}
119
+	return 0;
120
+}
114 121
 
115 122
 int pv_parse_phonenum_name(pv_spec_p sp, str *in)
116 123
 {
Browse code

phonenum: added ccname attribute

- get code for country name
- GH #1576

Daniel-Constantin Mierla authored on 02/07/2018 19:51:26
Showing 1 changed files
... ...
@@ -181,6 +181,8 @@ int pv_parse_phonenum_name(pv_spec_p sp, str *in)
181 181
 		case 6:
182 182
 			if(strncmp(pvs.s, "number", 6) == 0)
183 183
 				gpv->type = 0;
184
+			else if(strncmp(pvs.s, "ccname", 6) == 0)
185
+				gpv->type = 7;
184 186
 			else
185 187
 				goto error;
186 188
 			break;
... ...
@@ -255,6 +257,10 @@ int pv_get_phonenum(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
255 257
 			return pv_get_sintval(msg, param, res, gpv->item->r.record->cctel);
256 258
 		case 6: /* valid */
257 259
 			return pv_get_sintval(msg, param, res, gpv->item->r.record->valid);
260
+		case 7: /* ccname */
261
+			if(gpv->item->r.record->ccname==NULL)
262
+				return pv_get_null(msg, param, res);
263
+			return pv_get_strzval(msg, param, res, gpv->item->r.record->ccname);
258 264
 		default: /* number */
259 265
 			if(gpv->item->r.record->number==NULL)
260 266
 				return pv_get_null(msg, param, res);
Browse code

phonenum: set the order of params for phonenum_match_cn()

Daniel-Constantin Mierla authored on 28/03/2018 06:26:02
Showing 1 changed files
... ...
@@ -289,7 +289,7 @@ void phonenum_pv_reset(str *name)
289 289
 	memset(gr, 0, sizeof(sr_phonenum_record_t));
290 290
 }
291 291
 
292
-int phonenum_update_pv(str *tomatch, str *name, str *cncode)
292
+int phonenum_update_pv(str *tomatch, str *cncode, str *name)
293 293
 {
294 294
 	sr_phonenum_record_t *gr = NULL;
295 295
 
Browse code

phonenum: new function phonenum_match_cn(...)

- match a phone number within a specific country provided by country
code two letter

Daniel-Constantin Mierla authored on 27/03/2018 19:59:24
Showing 1 changed files
... ...
@@ -289,7 +289,7 @@ void phonenum_pv_reset(str *name)
289 289
 	memset(gr, 0, sizeof(sr_phonenum_record_t));
290 290
 }
291 291
 
292
-int phonenum_update_pv(str *tomatch, str *name)
292
+int phonenum_update_pv(str *tomatch, str *name, str *cncode)
293 293
 {
294 294
 	sr_phonenum_record_t *gr = NULL;
295 295
 
... ...
@@ -310,7 +310,8 @@ int phonenum_update_pv(str *tomatch, str *name)
310 310
 	strncpy(gr->tomatch, tomatch->s, tomatch->len);
311 311
 	gr->tomatch[tomatch->len] = '\0';
312 312
 	LM_DBG("attempt to match: %s\n", gr->tomatch);
313
-	gr->record = telnum_parse(gr->tomatch, "ZZ");
313
+	gr->record = telnum_parse(gr->tomatch,
314
+			(cncode && cncode->len>0)?cncode->s:"ZZ");
314 315
 	if(gr->record == NULL) {
315 316
 		LM_DBG("no match for: %s\n", gr->tomatch);
316 317
 		return -2;
Browse code

phonenum: fixed lenght in pv name comparisons

Daniel-Constantin Mierla authored on 21/03/2018 13:48:58
Showing 1 changed files
... ...
@@ -165,19 +165,19 @@ int pv_parse_phonenum_name(pv_spec_p sp, str *in)
165 165
 
166 166
 	switch(pvs.len) {
167 167
 		case 5:
168
-			if(strncmp(pvs.s, "ltype", 6) == 0)
168
+			if(strncmp(pvs.s, "ltype", 5) == 0)
169 169
 				gpv->type = 2;
170
-			else if(strncmp(pvs.s, "ndesc", 6) == 0)
170
+			else if(strncmp(pvs.s, "ndesc", 5) == 0)
171 171
 				gpv->type = 3;
172
-			else if(strncmp(pvs.s, "error", 6) == 0)
172
+			else if(strncmp(pvs.s, "error", 5) == 0)
173 173
 				gpv->type = 4;
174
-			else if(strncmp(pvs.s, "cctel", 6) == 0)
174
+			else if(strncmp(pvs.s, "cctel", 5) == 0)
175 175
 				gpv->type = 5;
176
-			else if(strncmp(pvs.s, "valid", 6) == 0)
176
+			else if(strncmp(pvs.s, "valid", 5) == 0)
177 177
 				gpv->type = 6;
178 178
 			else
179 179
 				goto error;
180
-			break;		
180
+			break;
181 181
 		case 6:
182 182
 			if(strncmp(pvs.s, "number", 6) == 0)
183 183
 				gpv->type = 0;
... ...
@@ -315,7 +315,10 @@ int phonenum_update_pv(str *tomatch, str *name)
315 315
 		LM_DBG("no match for: %s\n", gr->tomatch);
316 316
 		return -2;
317 317
 	}
318
-	LM_DBG("phonenum PV updated for: %s\n", gr->tomatch);
318
+	LM_DBG("phonenum PV updated for: %s (%d/%s/%s)\n", gr->tomatch,
319
+			gr->record->valid,
320
+			(gr->record->normalized)?gr->record->normalized:"none",
321
+			(gr->record->error)?gr->record->error:"none");
319 322
 
320 323
 	return 1;
321 324
 }
Browse code

phonenum: set record after phone number lookup and return pv attributes

Daniel-Constantin Mierla authored on 08/11/2017 10:59:31
Showing 1 changed files
... ...
@@ -35,14 +35,11 @@
35 35
 #include "cphonenumber.h"
36 36
 #include "phonenum_pv.h"
37 37
 
38
+/* clang-format off */
38 39
 typedef struct _sr_phonenum_record {
39 40
 	telnum_t *record;
40
-	char *number;
41
-	char *country;
42
-	char *region;
43
-	char *operator;
44 41
 	char tomatch[256];
45
-	int flags;
42
+	long flags;
46 43
 } sr_phonenum_record_t;
47 44
 
48 45
 typedef struct _sr_phonenum_item {
... ...
@@ -56,6 +53,7 @@ typedef struct _phonenum_pv {
56 53
 	sr_phonenum_item_t *item;
57 54
 	int type;
58 55
 } phonenum_pv_t;
56
+/* clang-format on */
59 57
 
60 58
 
61 59
 static sr_phonenum_item_t *_sr_phonenum_list = NULL;
... ...
@@ -65,13 +63,12 @@ sr_phonenum_record_t *sr_phonenum_get_record(str *name)
65 63
 	sr_phonenum_item_t *it = NULL;
66 64
 	unsigned int hashid = 0;
67 65
 
68
-	hashid =  get_hash1_raw(name->s, name->len);
66
+	hashid = get_hash1_raw(name->s, name->len);
69 67
 
70 68
 	it = _sr_phonenum_list;
71
-	while(it!=NULL)
72
-	{
73
-		if(it->hashid==hashid && it->pvclass.len == name->len
74
-				&& strncmp(it->pvclass.s, name->s, name->len)==0)
69
+	while(it != NULL) {
70
+		if(it->hashid == hashid && it->pvclass.len == name->len
71
+				&& strncmp(it->pvclass.s, name->s, name->len) == 0)
75 72
 			return &it->r;
76 73
 		it = it->next;
77 74
 	}
... ...
@@ -83,27 +80,24 @@ sr_phonenum_item_t *sr_phonenum_add_item(str *name)
83 80
 	sr_phonenum_item_t *it = NULL;
84 81
 	unsigned int hashid = 0;
85 82
 
86
-	hashid =  get_hash1_raw(name->s, name->len);
83
+	hashid = get_hash1_raw(name->s, name->len);
87 84
 
88 85
 	it = _sr_phonenum_list;
89
-	while(it!=NULL)
90
-	{
91
-		if(it->hashid==hashid && it->pvclass.len == name->len
92
-				&& strncmp(it->pvclass.s, name->s, name->len)==0)
86
+	while(it != NULL) {
87
+		if(it->hashid == hashid && it->pvclass.len == name->len
88
+				&& strncmp(it->pvclass.s, name->s, name->len) == 0)
93 89
 			return it;
94 90
 		it = it->next;
95 91
 	}
96 92
 	/* add new */
97
-	it = (sr_phonenum_item_t*)pkg_malloc(sizeof(sr_phonenum_item_t));
98
-	if(it==NULL)
99
-	{
93
+	it = (sr_phonenum_item_t *)pkg_malloc(sizeof(sr_phonenum_item_t));
94
+	if(it == NULL) {
100 95
 		LM_ERR("no more pkg\n");
101 96
 		return NULL;
102 97
 	}
103 98
 	memset(it, 0, sizeof(sr_phonenum_item_t));
104
-	it->pvclass.s = (char*)pkg_malloc(name->len+1);
105
-	if(it->pvclass.s==NULL)
106
-	{
99
+	it->pvclass.s = (char *)pkg_malloc(name->len + 1);
100
+	if(it->pvclass.s == NULL) {
107 101
 		LM_ERR("no more pkg.\n");
108 102
 		pkg_free(it);
109 103
 		return NULL;
... ...
@@ -120,96 +114,103 @@ sr_phonenum_item_t *sr_phonenum_add_item(str *name)
120 114
 
121 115
 int pv_parse_phonenum_name(pv_spec_p sp, str *in)
122 116
 {
123
-	phonenum_pv_t *gpv=NULL;
117
+	phonenum_pv_t *gpv = NULL;
124 118
 	char *p;
125 119
 	str pvc;
126 120
 	str pvs;
127
-	if(sp==NULL || in==NULL || in->len<=0)
121
+	if(sp == NULL || in == NULL || in->len <= 0)
128 122
 		return -1;
129 123
 
130
-	gpv = (phonenum_pv_t*)pkg_malloc(sizeof(phonenum_pv_t));
131
-	if(gpv==NULL)
124
+	gpv = (phonenum_pv_t *)pkg_malloc(sizeof(phonenum_pv_t));
125
+	if(gpv == NULL)
132 126
 		return -1;
133 127
 
134 128
 	memset(gpv, 0, sizeof(phonenum_pv_t));
135 129
 
136 130
 	p = in->s;
137 131
 
138
-	while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
132
+	while(p < in->s + in->len
133
+			&& (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r'))
139 134
 		p++;
140
-	if(p>in->s+in->len || *p=='\0')
135
+	if(p > in->s + in->len || *p == '\0')
141 136
 		goto error;
142 137
 	pvc.s = p;
143
-	while(p < in->s + in->len)
144
-	{
145
-		if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
138
+	while(p < in->s + in->len) {
139
+		if(*p == '=' || *p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
146 140
 			break;
147 141
 		p++;
148 142
 	}
149
-	if(p>in->s+in->len || *p=='\0')
143
+	if(p > in->s + in->len || *p == '\0')
150 144
 		goto error;
151 145
 	pvc.len = p - pvc.s;
152
-	if(*p!='=')
153
-	{
154
-		while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
146
+	if(*p != '=') {
147
+		while(p < in->s + in->len
148
+				&& (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r'))
155 149
 			p++;
156
-		if(p>in->s+in->len || *p=='\0' || *p!='=')
150
+		if(p > in->s + in->len || *p == '\0' || *p != '=')
157 151
 			goto error;
158 152
 	}
159 153
 	p++;
160
-	if(*p!='>')
154
+	if(*p != '>')
161 155
 		goto error;
162 156
 	p++;
163 157
 
164 158
 	pvs.len = in->len - (int)(p - in->s);
165 159
 	pvs.s = p;
166
-	LM_DBG("phonenum [%.*s] - key [%.*s]\n", pvc.len, pvc.s,
167
-			pvs.len, pvs.s);
160
+	LM_DBG("phonenum [%.*s] - key [%.*s]\n", pvc.len, pvc.s, pvs.len, pvs.s);
168 161
 
169 162
 	gpv->item = sr_phonenum_add_item(&pvc);
170
-	if(gpv->item==NULL)
163
+	if(gpv->item == NULL)
171 164
 		goto error;
172 165
 
173
-	switch(pvs.len)
174
-	{
166
+	switch(pvs.len) {
167
+		case 5:
168
+			if(strncmp(pvs.s, "ltype", 6) == 0)
169
+				gpv->type = 2;
170
+			else if(strncmp(pvs.s, "ndesc", 6) == 0)
171
+				gpv->type = 3;
172
+			else if(strncmp(pvs.s, "error", 6) == 0)
173
+				gpv->type = 4;
174
+			else if(strncmp(pvs.s, "cctel", 6) == 0)
175
+				gpv->type = 5;
176
+			else if(strncmp(pvs.s, "valid", 6) == 0)
177
+				gpv->type = 6;
178
+			else
179
+				goto error;
180
+			break;		
175 181
 		case 6:
176
-			if(strncmp(pvs.s, "number", 6)==0)
182
+			if(strncmp(pvs.s, "number", 6) == 0)
177 183
 				gpv->type = 0;
178
-			else if(strncmp(pvs.s, "region", 6)==0)
179
-				gpv->type = 2;
180
-			else goto error;
181
-		break;
182
-		case 7:
183
-			if(strncmp(pvs.s, "country", 7)==0)
184
+			else
185
+				goto error;
186
+			break;
187
+		case 10:
188
+			if(strncmp(pvs.s, "normalized", 10) == 0)
184 189
 				gpv->type = 1;
185
-			else goto error;
186
-		break;
187
-		case 8:
188
-			if(strncmp(pvs.s, "operator", 8)==0)
189
-				gpv->type = 3;
190
-			else goto error;
191
-		break;
190
+			else
191
+				goto error;
192
+			break;
192 193
 		default:
193 194
 			goto error;
194 195
 	}
195
-	sp->pvp.pvn.u.dname = (void*)gpv;
196
+	sp->pvp.pvn.u.dname = (void *)gpv;
196 197
 	sp->pvp.pvn.type = PV_NAME_OTHER;
197 198
 
198 199
 	return 0;
199 200
 
200 201
 error:
201
-	if(gpv!=NULL)
202
+	if(gpv != NULL)
202 203
 		pkg_free(gpv);
203 204
 
204 205
 	LM_ERR("error at PV phonenum name: %.*s\n", in->len, in->s);
205 206
 	return -1;
206 207
 }
207 208
 
208
-int pv_phonenum_get_strzval(struct sip_msg *msg, pv_param_t *param,
209
-		pv_value_t *res, char *sval)
209
+int pv_phonenum_get_strzval(
210
+		struct sip_msg *msg, pv_param_t *param, pv_value_t *res, char *sval)
210 211
 {
211 212
 	str s;
212
-	if(sval==NULL)
213
+	if(sval == NULL)
213 214
 		return pv_get_null(msg, param, res);
214 215
 
215 216
 	s.s = sval;
... ...
@@ -217,30 +218,47 @@ int pv_phonenum_get_strzval(struct sip_msg *msg, pv_param_t *param,
217 218
 	return pv_get_strval(msg, param, res, &s);
218 219
 }
219 220
 
220
-int pv_get_phonenum(struct sip_msg *msg, pv_param_t *param,
221
-		pv_value_t *res)
221
+int pv_get_phonenum(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
222 222
 {
223 223
 	phonenum_pv_t *gpv;
224 224
 
225
-	if(msg==NULL || param==NULL)
225
+	if(msg == NULL || param == NULL)
226 226
 		return -1;
227 227
 
228
-	gpv = (phonenum_pv_t*)param->pvn.u.dname;
229
-	if(gpv==NULL)
228
+	gpv = (phonenum_pv_t *)param->pvn.u.dname;
229
+	if(gpv == NULL)
230 230
 		return -1;
231
-	if(gpv->item==NULL)
231
+	if(gpv->item == NULL)
232
+		return pv_get_null(msg, param, res);
233
+	if(gpv->item->r.record==NULL)
232 234
 		return pv_get_null(msg, param, res);
233 235
 
234
-	switch(gpv->type)
235
-	{
236
-		case 1: /* country */
237
-			return pv_get_null(msg, param, res);
238
-		case 2: /* region */
239
-			return pv_get_null(msg, param, res);
240
-		case 3: /* operator */
241
-			return pv_get_null(msg, param, res);
236
+	switch(gpv->type) {
237
+		case 1: /* normalized */
238
+			if(gpv->item->r.record->normalized==NULL)
239
+				return pv_get_null(msg, param, res);
240
+			return pv_get_strzval(msg, param, res,
241
+						gpv->item->r.record->normalized);
242
+		case 2: /* ltype */
243
+			if(gpv->item->r.record->ltype==NULL)
244
+				return pv_get_null(msg, param, res);
245
+			return pv_get_strzval(msg, param, res, gpv->item->r.record->ltype);
246
+		case 3: /* ndesc */
247
+			if(gpv->item->r.record->ndesc==NULL)
248
+				return pv_get_null(msg, param, res);
249
+			return pv_get_strzval(msg, param, res, gpv->item->r.record->ndesc);
250
+		case 4: /* error */
251
+			if(gpv->item->r.record->error==NULL)
252
+				return pv_get_null(msg, param, res);
253
+			return pv_get_strzval(msg, param, res, gpv->item->r.record->error);
254
+		case 5: /* cctel */
255
+			return pv_get_sintval(msg, param, res, gpv->item->r.record->cctel);
256
+		case 6: /* valid */
257
+			return pv_get_sintval(msg, param, res, gpv->item->r.record->valid);
242 258
 		default: /* number */
243
-			return pv_get_null(msg, param, res);
259
+			if(gpv->item->r.record->number==NULL)
260
+				return pv_get_null(msg, param, res);
261
+			return pv_get_strzval(msg, param, res, gpv->item->r.record->number);
244 262
 	}
245 263
 }
246 264
 
... ...
@@ -263,8 +281,11 @@ void phonenum_pv_reset(str *name)
263 281
 
264 282
 	gr = sr_phonenum_get_record(name);
265 283
 
266
-	if(gr==NULL)
284
+	if(gr == NULL)
267 285
 		return;
286
+	if(gr->record != NULL) {
287
+		telnum_free(gr->record);
288
+	}
268 289
 	memset(gr, 0, sizeof(sr_phonenum_record_t));
269 290
 }
270 291
 
... ...
@@ -272,24 +293,25 @@ int phonenum_update_pv(str *tomatch, str *name)
272 293
 {
273 294
 	sr_phonenum_record_t *gr = NULL;
274 295
 
275
-	if(tomatch->len>255)
276
-	{
296
+	if(tomatch->len > 255) {
277 297
 		LM_DBG("target too long (max 255): %s\n", tomatch->s);
278 298
 		return -3;
279 299
 	}
280 300
 
281 301
 	gr = sr_phonenum_get_record(name);
282
-	if(gr==NULL)
283
-	{
302
+	if(gr == NULL) {
284 303
 		LM_DBG("container not found: %s\n", tomatch->s);
285
-		return - 4;
304
+		return -4;
305
+	}
306
+	if(gr->record != NULL) {
307
+		telnum_free(gr->record);
286 308
 	}
287 309
 
288 310
 	strncpy(gr->tomatch, tomatch->s, tomatch->len);
289 311
 	gr->tomatch[tomatch->len] = '\0';
290 312
 	LM_DBG("attempt to match: %s\n", gr->tomatch);
291
-	if (gr->record == NULL)
292
-	{
313
+	gr->record = telnum_parse(gr->tomatch, "ZZ");
314
+	if(gr->record == NULL) {
293 315
 		LM_DBG("no match for: %s\n", gr->tomatch);
294 316
 		return -2;
295 317
 	}
Browse code

phonenum: new module to do lookup on phone numbers

- relies on libphonenumber to get the attributes associated with the
phone number

Daniel-Constantin Mierla authored on 16/10/2017 08:54:44
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,299 @@
1
+/**
2
+ *
3
+ * Copyright (C) 2017 Daniel-Constantin Mierla (asipto.com)
4
+ *
5
+ * This file is part of Kamailio, a free SIP server.
6
+ *
7
+ * This file 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
+ *
13
+ * This file is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program; if not, write to the Free Software
20
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21
+ *
22
+ */
23
+
24
+
25
+#include <assert.h>
26
+#include <ctype.h>
27
+#include <string.h>
28
+#include <stdlib.h>
29
+#include <time.h>
30
+
31
+#include "../../core/dprint.h"
32
+#include "../../core/hashes.h"
33
+#include "../../core/pvar.h"
34
+
35
+#include "cphonenumber.h"
36
+#include "phonenum_pv.h"
37
+
38
+typedef struct _sr_phonenum_record {
39
+	telnum_t *record;
40
+	char *number;
41
+	char *country;
42
+	char *region;
43
+	char *operator;
44
+	char tomatch[256];
45
+	int flags;
46
+} sr_phonenum_record_t;
47
+
48
+typedef struct _sr_phonenum_item {
49
+	str pvclass;
50
+	unsigned int hashid;
51
+	sr_phonenum_record_t r;
52
+	struct _sr_phonenum_item *next;
53
+} sr_phonenum_item_t;
54
+
55
+typedef struct _phonenum_pv {
56
+	sr_phonenum_item_t *item;
57
+	int type;
58
+} phonenum_pv_t;
59
+
60
+
61
+static sr_phonenum_item_t *_sr_phonenum_list = NULL;
62
+
63
+sr_phonenum_record_t *sr_phonenum_get_record(str *name)
64
+{
65
+	sr_phonenum_item_t *it = NULL;
66
+	unsigned int hashid = 0;
67
+
68
+	hashid =  get_hash1_raw(name->s, name->len);
69
+
70
+	it = _sr_phonenum_list;
71
+	while(it!=NULL)
72
+	{
73
+		if(it->hashid==hashid && it->pvclass.len == name->len
74
+				&& strncmp(it->pvclass.s, name->s, name->len)==0)
75
+			return &it->r;
76
+		it = it->next;
77
+	}
78
+	return NULL;
79
+}
80
+
81
+sr_phonenum_item_t *sr_phonenum_add_item(str *name)
82
+{
83
+	sr_phonenum_item_t *it = NULL;
84
+	unsigned int hashid = 0;
85
+
86
+	hashid =  get_hash1_raw(name->s, name->len);
87
+
88
+	it = _sr_phonenum_list;
89
+	while(it!=NULL)
90
+	{
91
+		if(it->hashid==hashid && it->pvclass.len == name->len
92
+				&& strncmp(it->pvclass.s, name->s, name->len)==0)
93
+			return it;
94
+		it = it->next;
95
+	}
96
+	/* add new */
97
+	it = (sr_phonenum_item_t*)pkg_malloc(sizeof(sr_phonenum_item_t));
98
+	if(it==NULL)
99
+	{
100
+		LM_ERR("no more pkg\n");
101
+		return NULL;
102
+	}
103
+	memset(it, 0, sizeof(sr_phonenum_item_t));
104
+	it->pvclass.s = (char*)pkg_malloc(name->len+1);
105
+	if(it->pvclass.s==NULL)
106
+	{
107
+		LM_ERR("no more pkg.\n");
108
+		pkg_free(it);
109
+		return NULL;
110
+	}
111
+	memcpy(it->pvclass.s, name->s, name->len);
112
+	it->pvclass.s[name->len] = '\0';
113
+	it->pvclass.len = name->len;
114
+	it->hashid = hashid;
115
+	it->next = _sr_phonenum_list;
116
+	_sr_phonenum_list = it;
117
+	return it;
118
+}
119
+
120
+
121
+int pv_parse_phonenum_name(pv_spec_p sp, str *in)
122
+{
123
+	phonenum_pv_t *gpv=NULL;
124
+	char *p;
125
+	str pvc;
126
+	str pvs;
127
+	if(sp==NULL || in==NULL || in->len<=0)
128
+		return -1;
129
+
130
+	gpv = (phonenum_pv_t*)pkg_malloc(sizeof(phonenum_pv_t));
131
+	if(gpv==NULL)
132
+		return -1;
133
+
134
+	memset(gpv, 0, sizeof(phonenum_pv_t));
135
+
136
+	p = in->s;
137
+
138
+	while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
139
+		p++;
140
+	if(p>in->s+in->len || *p=='\0')
141
+		goto error;
142
+	pvc.s = p;
143
+	while(p < in->s + in->len)
144
+	{
145
+		if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r')
146
+			break;
147
+		p++;
148
+	}
149
+	if(p>in->s+in->len || *p=='\0')
150
+		goto error;
151
+	pvc.len = p - pvc.s;
152
+	if(*p!='=')
153
+	{
154
+		while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
155
+			p++;
156
+		if(p>in->s+in->len || *p=='\0' || *p!='=')
157
+			goto error;
158
+	}
159
+	p++;
160
+	if(*p!='>')
161
+		goto error;
162
+	p++;
163
+
164
+	pvs.len = in->len - (int)(p - in->s);
165
+	pvs.s = p;
166
+	LM_DBG("phonenum [%.*s] - key [%.*s]\n", pvc.len, pvc.s,
167
+			pvs.len, pvs.s);
168
+
169
+	gpv->item = sr_phonenum_add_item(&pvc);
170
+	if(gpv->item==NULL)
171
+		goto error;
172
+
173
+	switch(pvs.len)
174
+	{
175
+		case 6:
176
+			if(strncmp(pvs.s, "number", 6)==0)
177
+				gpv->type = 0;
178
+			else if(strncmp(pvs.s, "region", 6)==0)
179
+				gpv->type = 2;
180
+			else goto error;
181
+		break;
182
+		case 7:
183
+			if(strncmp(pvs.s, "country", 7)==0)
184
+				gpv->type = 1;
185
+			else goto error;
186
+		break;
187
+		case 8:
188
+			if(strncmp(pvs.s, "operator", 8)==0)
189
+				gpv->type = 3;
190
+			else goto error;
191
+		break;
192
+		default:
193
+			goto error;
194
+	}
195
+	sp->pvp.pvn.u.dname = (void*)gpv;
196
+	sp->pvp.pvn.type = PV_NAME_OTHER;
197
+
198
+	return 0;
199
+
200
+error:
201
+	if(gpv!=NULL)
202
+		pkg_free(gpv);
203
+
204
+	LM_ERR("error at PV phonenum name: %.*s\n", in->len, in->s);
205
+	return -1;
206
+}
207
+
208
+int pv_phonenum_get_strzval(struct sip_msg *msg, pv_param_t *param,
209
+		pv_value_t *res, char *sval)
210
+{
211
+	str s;
212
+	if(sval==NULL)
213
+		return pv_get_null(msg, param, res);
214
+
215
+	s.s = sval;
216
+	s.len = strlen(s.s);
217
+	return pv_get_strval(msg, param, res, &s);
218
+}
219
+
220
+int pv_get_phonenum(struct sip_msg *msg, pv_param_t *param,
221
+		pv_value_t *res)
222
+{
223
+	phonenum_pv_t *gpv;
224
+
225
+	if(msg==NULL || param==NULL)
226
+		return -1;
227
+
228
+	gpv = (phonenum_pv_t*)param->pvn.u.dname;
229
+	if(gpv==NULL)
230
+		return -1;
231
+	if(gpv->item==NULL)
232
+		return pv_get_null(msg, param, res);
233
+
234
+	switch(gpv->type)
235
+	{
236
+		case 1: /* country */
237
+			return pv_get_null(msg, param, res);
238
+		case 2: /* region */
239
+			return pv_get_null(msg, param, res);
240
+		case 3: /* operator */
241
+			return pv_get_null(msg, param, res);
242
+		default: /* number */
243
+			return pv_get_null(msg, param, res);
244
+	}
245
+}
246
+
247
+int phonenum_init_pv(int smode)
248
+{
249
+	return 0;
250
+}
251
+
252
+void phonenum_destroy_list(void)
253
+{
254
+}
255
+
256
+void phonenum_destroy_pv(void)
257
+{
258
+}
259
+
260
+void phonenum_pv_reset(str *name)
261
+{
262
+	sr_phonenum_record_t *gr = NULL;
263
+
264
+	gr = sr_phonenum_get_record(name);
265
+
266
+	if(gr==NULL)
267
+		return;
268
+	memset(gr, 0, sizeof(sr_phonenum_record_t));
269
+}
270
+
271
+int phonenum_update_pv(str *tomatch, str *name)
272
+{
273
+	sr_phonenum_record_t *gr = NULL;
274
+
275
+	if(tomatch->len>255)
276
+	{
277
+		LM_DBG("target too long (max 255): %s\n", tomatch->s);
278
+		return -3;
279
+	}
280
+
281
+	gr = sr_phonenum_get_record(name);
282
+	if(gr==NULL)
283
+	{
284
+		LM_DBG("container not found: %s\n", tomatch->s);
285
+		return - 4;
286
+	}
287
+
288
+	strncpy(gr->tomatch, tomatch->s, tomatch->len);
289
+	gr->tomatch[tomatch->len] = '\0';
290
+	LM_DBG("attempt to match: %s\n", gr->tomatch);
291
+	if (gr->record == NULL)
292
+	{
293
+		LM_DBG("no match for: %s\n", gr->tomatch);
294
+		return -2;
295
+	}
296
+	LM_DBG("phonenum PV updated for: %s\n", gr->tomatch);
297
+
298
+	return 1;
299
+}