Textops in list prefix function
... | ... |
@@ -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, |