Browse code

Merge pull request #1423 from kamailio/textops_in_list_prefix_function

Textops in list prefix function

Daniel-Constantin Mierla authored on 08/02/2018 12:41:31 • GitHub committed on 08/02/2018 12:41:31
Showing 2 changed files
... ...
@@ -1342,7 +1342,7 @@ if(is_privacy("id"))
1342 1342
 ...
1343 1343
 $var(subject) = "fi";
1344 1344
 $var(list) = "dk,fi,no,se";
1345
-if (in_list("$var(subject)", "$var(list)", ",") {
1345
+if (in_list("$var(subject)", "$var(list)", ",")) {
1346 1346
     xlog("L_INFO", "subject is found in list\n");
1347 1347
 }
1348 1348
 ...
... ...
@@ -1350,6 +1350,30 @@ if (in_list("$var(subject)", "$var(list)", ",") {
1350 1350
 		</example>
1351 1351
 	</section>
1352 1352
 
1353
+	<section id="textops.f.in_list_prefix">
1354
+		<title>
1355
+			<function moreinfo="none">in_list_prefix(subject, list, separator)</function>
1356
+		</title>
1357
+		<para>
1358
+		Function checks if any element in list string is a prefix for subject string where list items are separated by separator string.  Subject and list strings may contain pseudo variables.  Separator string needs to be one character long.  Returns 1 if subject is found and -1 otherwise.
1359
+    	        </para>
1360
+		<para>
1361
+		Function can be used from all kinds of routes.
1362
+		</para>
1363
+		<example>
1364
+			<title><function>in_list()</function> usage</title>
1365
+			<programlisting format="linespecific">
1366
+...
1367
+$var(subject) = "final";
1368
+$var(list) = "dk,fi,no,se";
1369
+if (in_list_prefix("$var(subject)", "$var(list)", ",")) {
1370
+    xlog("L_INFO", "prefix for subject is found in list\n");
1371
+}
1372
+...
1373
+			</programlisting>
1374
+		</example>
1375
+	</section>
1376
+
1353 1377
 	<section id="textops.f.cmp_str">
1354 1378
 		<title>
1355 1379
 		<function moreinfo="none">cmp_str(str1, str2)</function>
... ...
@@ -125,6 +125,8 @@ static int is_method_f(struct sip_msg* msg, char* , char *);
125 125
 static int has_body_f(struct sip_msg *msg, char *type, char *str2 );
126 126
 static int in_list_f(struct sip_msg* _msg, char* _subject, char* _list,
127 127
 		char* _sep);
128
+static int in_list_prefix_f(struct sip_msg* _msg, char* _subject, char* _list,
129
+		char* _sep);
128 130
 static int cmp_str_f(struct sip_msg *msg, char *str1, char *str2 );
129 131
 static int cmp_istr_f(struct sip_msg *msg, char *str1, char *str2 );
130 132
 static int starts_with_f(struct sip_msg *msg, char *str1, char *str2 );
... ...
@@ -139,7 +141,9 @@ static int fixup_method(void** param, int param_no);
139 141
 static int add_header_fixup(void** param, int param_no);
140 142
 static int fixup_body_type(void** param, int param_no);
141 143
 static int fixup_in_list(void** param, int param_no);
144
+static int fixup_in_list_prefix(void** param, int param_no);
142 145
 static int fixup_free_in_list(void** param, int param_no);
146
+static int fixup_free_in_list_prefix(void** param, int param_no);
143 147
 int fixup_regexpNL_none(void** param, int param_no);
144 148
 static int fixup_search_hf(void** param, int param_no);
145 149
 static int fixup_subst_hf(void** param, int param_no);
... ...
@@ -259,6 +263,9 @@ static cmd_export_t cmds[]={
259 263
 	{"in_list", (cmd_function)in_list_f, 3, fixup_in_list,
260 264
 		fixup_free_in_list,
261 265
 		ANY_ROUTE},
266
+	{"in_list_prefix", (cmd_function)in_list_prefix_f, 3,
267
+		fixup_in_list_prefix, fixup_free_in_list_prefix,
268
+		ANY_ROUTE},
262 269
 	{"cmp_str",  (cmd_function)cmp_str_f, 2,
263 270
 		fixup_spve_spve, 0,
264 271
 		ANY_ROUTE},
... ...
@@ -3007,6 +3014,41 @@ static int fixup_free_in_list(void** param, int param_no)
3007 3014
 	return -1;
3008 3015
 }
3009 3016
 
3017
+/*
3018
+ * Fix in_list_prefix params: subject and list (strings that may contain pvars),
3019
+ * separator (string)
3020
+ */
3021
+static int fixup_in_list_prefix(void** param, int param_no)
3022
+{
3023
+	if ((param_no == 1) || (param_no == 2)) return fixup_spve_null(param, 1);
3024
+
3025
+	if (param_no == 3) {
3026
+		if ((strlen((char *)*param) != 1) || (*((char *)(*param)) == 0)) {
3027
+			LM_ERR("invalid separator parameter\n");
3028
+			return -1;
3029
+		}
3030
+		return 0;
3031
+	}
3032
+
3033
+	LM_ERR("invalid parameter number <%d>\n", param_no);
3034
+	return -1;
3035
+}
3036
+
3037
+/*
3038
+ * Free in_list_prefix params
3039
+ */
3040
+static int fixup_free_in_list_prefix(void** param, int param_no)
3041
+{
3042
+	if ((param_no == 1) || (param_no == 2)) {
3043
+		return fixup_free_spve_null(param, 1);
3044
+	}
3045
+
3046
+	if (param_no == 3) return 0;
3047
+
3048
+	LM_ERR("invalid parameter number <%d>\n", param_no);
3049
+	return -1;
3050
+}
3051
+
3010 3052
 static int add_header_fixup(void** param, int param_no)
3011 3053
 {
3012 3054
 	if(param_no==1)
... ...
@@ -3242,6 +3284,112 @@ int in_list_f(struct sip_msg* _m, char* _subject, char* _list, char* _sep)
3242 3284
 	return ki_in_list(_m, &subject, &list, &sep);
3243 3285
 }
3244 3286
 
3287
+/*
3288
+ * Checks if an element in list is a prefix for subject
3289
+ */
3290
+int ki_in_list_prefix(sip_msg_t* _m, str* subject, str* list, str* vsep)
3291
+{
3292
+	int sep;
3293
+	char *at, *past, *next_sep, *s;
3294
+	
3295
+	if(subject==NULL || subject->len<=0 || list==NULL || list->len<=0
3296
+			|| vsep==NULL || vsep->len<=0)
3297
+		return -1;
3298
+
3299
+	sep = vsep->s[0];
3300
+
3301
+	at = list->s;
3302
+	past = list->s + list->len;
3303
+
3304
+	/* Eat leading white space */
3305
+	while ((at < past) &&
3306
+			((*at == ' ') || (*at == '\t') || (*at == '\r') || (*at == '\n') )) {
3307
+		at++;
3308
+	}
3309
+
3310
+	while (at < past) {
3311
+		next_sep = index(at, sep);
3312
+		s = next_sep;
3313
+		int list_element_len;
3314
+
3315
+		if (s == NULL) {
3316
+			/* Eat trailing white space */
3317
+			while ((at < past) &&
3318
+					((*(past-1) == ' ') || (*(past-1) == '\t')
3319
+						|| (*(past-1) == '\r') || (*(past-1) == '\n') )) {
3320
+				past--;
3321
+			}
3322
+			list_element_len = past - at;
3323
+			if (list_element_len == 0) {
3324
+				/* There is no list element */
3325
+				return -1;
3326
+			}
3327
+			if (list_element_len > subject->len) {
3328
+				/* Length of list element is greater than subject length */
3329
+				return -1;
3330
+			}
3331
+			if (strncmp(at, subject->s, list_element_len) != 0) {
3332
+				return -1;
3333
+			}
3334
+			/* Prefix match found */
3335
+			return 1;
3336
+
3337
+		} else {
3338
+			/* Eat trailing white space */
3339
+			while ((at < s) &&
3340
+					((*(s-1) == ' ') || (*(s-1) == '\t') || (*(s-1) == '\r')
3341
+						|| (*(s-1) == '\n') )) {
3342
+				s--;
3343
+			}
3344
+			list_element_len = s - at;
3345
+			if (list_element_len == 0 || list_element_len > subject->len ||
3346
+				strncmp(at, subject->s, list_element_len) != 0) {
3347
+				/* Prefix match not found */
3348
+				at = next_sep + 1;
3349
+				/* Eat leading white space */
3350
+				while ((at < past) &&
3351
+						((*at == ' ') || (*at == '\t') || (*at == '\r')
3352
+							|| (*at == '\n') )) {
3353
+					at++;
3354
+				}
3355
+			} else {
3356
+				/* Prefix match found */
3357
+				return 1;
3358
+			}
3359
+		}
3360
+	}
3361
+
3362
+	return -1;
3363
+}
3364
+
3365
+/*
3366
+ * Checks if an element in list is a prefix for subject
3367
+ */
3368
+int in_list_prefix_f(struct sip_msg* _m, char* _subject, char* _list, char* _sep)
3369
+{
3370
+	str subject, list, sep;
3371
+	if (fixup_get_svalue(_m, (gparam_p)_subject, &subject) != 0) {
3372
+		LM_ERR("cannot get subject value\n");
3373
+		return -1;
3374
+	} else {
3375
+		if (subject.len == 0) {
3376
+			LM_ERR("subject cannot be empty string\n");
3377
+			return -1;
3378
+		}
3379
+	}
3380
+
3381
+	if (fixup_get_svalue(_m, (gparam_p)_list, &list) != 0) {
3382
+		LM_ERR("cannot get list value\n");
3383
+		return -1;
3384
+	} else {
3385
+		if (list.len == 0) return -1;
3386
+	}
3387
+	sep.s = _sep;
3388
+	sep.len = 1;
3389
+
3390
+	return ki_in_list_prefix(_m, &subject, &list, &sep);
3391
+}
3392
+
3245 3393
 static int cmp_str_f(struct sip_msg *msg, char *str1, char *str2 )
3246 3394
 {
3247 3395
 	str s1;
... ...
@@ -4049,6 +4197,11 @@ static sr_kemi_t sr_kemi_textops_exports[] = {
4049 4197
 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
4050 4198
 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
4051 4199
 	},
4200
+	{ str_init("textops"), str_init("in_list_prefix"),
4201
+		SR_KEMIP_INT, ki_in_list_prefix,
4202
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
4203
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
4204
+	},
4052 4205
 	{ str_init("textops"), str_init("cmp_str"),
4053 4206
 		SR_KEMIP_INT, ki_cmp_str,
4054 4207
 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,