diff --git a/src/modules/textops/doc/textops_admin.xml b/src/modules/textops/doc/textops_admin.xml
index f94183dabfa..f480ae2183c 100644
--- a/src/modules/textops/doc/textops_admin.xml
+++ b/src/modules/textops/doc/textops_admin.xml
@@ -1323,7 +1323,7 @@ if(is_privacy("id"))
...
$var(subject) = "fi";
$var(list) = "dk,fi,no,se";
-if (in_list("$var(subject)", "$var(list)", ",") {
+if (in_list("$var(subject)", "$var(list)", ",")) {
xlog("L_INFO", "subject is found in list\n");
}
...
@@ -1331,6 +1331,30 @@ if (in_list("$var(subject)", "$var(list)", ",") {
+
+
+ in_list_prefix(subject, list, separator)
+
+
+ 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.
+
+
+ Function can be used from all kinds of routes.
+
+
+ in_list() usage
+
+...
+$var(subject) = "final";
+$var(list) = "dk,fi,no,se";
+if (in_list_prefix("$var(subject)", "$var(list)", ",")) {
+ xlog("L_INFO", "prefix for subject is found in list\n");
+}
+...
+
+
+
+
cmp_str(str1, str2)
diff --git a/src/modules/textops/textops.c b/src/modules/textops/textops.c
index 97f1ecff127..8f493fdf39c 100644
--- a/src/modules/textops/textops.c
+++ b/src/modules/textops/textops.c
@@ -125,6 +125,8 @@ static int is_method_f(struct sip_msg* msg, char* , char *);
static int has_body_f(struct sip_msg *msg, char *type, char *str2 );
static int in_list_f(struct sip_msg* _msg, char* _subject, char* _list,
char* _sep);
+static int in_list_prefix_f(struct sip_msg* _msg, char* _subject, char* _list,
+ char* _sep);
static int cmp_str_f(struct sip_msg *msg, char *str1, char *str2 );
static int cmp_istr_f(struct sip_msg *msg, char *str1, char *str2 );
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);
static int add_header_fixup(void** param, int param_no);
static int fixup_body_type(void** param, int param_no);
static int fixup_in_list(void** param, int param_no);
+static int fixup_in_list_prefix(void** param, int param_no);
static int fixup_free_in_list(void** param, int param_no);
+static int fixup_free_in_list_prefix(void** param, int param_no);
int fixup_regexpNL_none(void** param, int param_no);
static int fixup_search_hf(void** param, int param_no);
static int fixup_subst_hf(void** param, int param_no);
@@ -259,6 +263,9 @@ static cmd_export_t cmds[]={
{"in_list", (cmd_function)in_list_f, 3, fixup_in_list,
fixup_free_in_list,
ANY_ROUTE},
+ {"in_list_prefix", (cmd_function)in_list_prefix_f, 3,
+ fixup_in_list_prefix, fixup_free_in_list_prefix,
+ ANY_ROUTE},
{"cmp_str", (cmd_function)cmp_str_f, 2,
fixup_spve_spve, 0,
ANY_ROUTE},
@@ -3007,6 +3014,41 @@ static int fixup_free_in_list(void** param, int param_no)
return -1;
}
+/*
+ * Fix in_list_prefix params: subject and list (strings that may contain pvars),
+ * separator (string)
+ */
+static int fixup_in_list_prefix(void** param, int param_no)
+{
+ if ((param_no == 1) || (param_no == 2)) return fixup_spve_null(param, 1);
+
+ if (param_no == 3) {
+ if ((strlen((char *)*param) != 1) || (*((char *)(*param)) == 0)) {
+ LM_ERR("invalid separator parameter\n");
+ return -1;
+ }
+ return 0;
+ }
+
+ LM_ERR("invalid parameter number <%d>\n", param_no);
+ return -1;
+}
+
+/*
+ * Free in_list_prefix params
+ */
+static int fixup_free_in_list_prefix(void** param, int param_no)
+{
+ if ((param_no == 1) || (param_no == 2)) {
+ return fixup_free_spve_null(param, 1);
+ }
+
+ if (param_no == 3) return 0;
+
+ LM_ERR("invalid parameter number <%d>\n", param_no);
+ return -1;
+}
+
static int add_header_fixup(void** param, int param_no)
{
if(param_no==1)
@@ -3242,6 +3284,112 @@ int in_list_f(struct sip_msg* _m, char* _subject, char* _list, char* _sep)
return ki_in_list(_m, &subject, &list, &sep);
}
+/*
+ * Checks if an element in list is a prefix for subject
+ */
+int ki_in_list_prefix(sip_msg_t* _m, str* subject, str* list, str* vsep)
+{
+ int sep;
+ char *at, *past, *next_sep, *s;
+
+ if(subject==NULL || subject->len<=0 || list==NULL || list->len<=0
+ || vsep==NULL || vsep->len<=0)
+ return -1;
+
+ sep = vsep->s[0];
+
+ at = list->s;
+ past = list->s + list->len;
+
+ /* Eat leading white space */
+ while ((at < past) &&
+ ((*at == ' ') || (*at == '\t') || (*at == '\r') || (*at == '\n') )) {
+ at++;
+ }
+
+ while (at < past) {
+ next_sep = index(at, sep);
+ s = next_sep;
+ int list_element_len;
+
+ if (s == NULL) {
+ /* Eat trailing white space */
+ while ((at < past) &&
+ ((*(past-1) == ' ') || (*(past-1) == '\t')
+ || (*(past-1) == '\r') || (*(past-1) == '\n') )) {
+ past--;
+ }
+ list_element_len = past - at;
+ if (list_element_len == 0) {
+ /* There is no list element */
+ return -1;
+ }
+ if (list_element_len > subject->len) {
+ /* Length of list element is greater than subject length */
+ return -1;
+ }
+ if (strncmp(at, subject->s, list_element_len) != 0) {
+ return -1;
+ }
+ /* Prefix match found */
+ return 1;
+
+ } else {
+ /* Eat trailing white space */
+ while ((at < s) &&
+ ((*(s-1) == ' ') || (*(s-1) == '\t') || (*(s-1) == '\r')
+ || (*(s-1) == '\n') )) {
+ s--;
+ }
+ list_element_len = s - at;
+ if (list_element_len == 0 || list_element_len > subject->len ||
+ strncmp(at, subject->s, list_element_len) != 0) {
+ /* Prefix match not found */
+ at = next_sep + 1;
+ /* Eat leading white space */
+ while ((at < past) &&
+ ((*at == ' ') || (*at == '\t') || (*at == '\r')
+ || (*at == '\n') )) {
+ at++;
+ }
+ } else {
+ /* Prefix match found */
+ return 1;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * Checks if an element in list is a prefix for subject
+ */
+int in_list_prefix_f(struct sip_msg* _m, char* _subject, char* _list, char* _sep)
+{
+ str subject, list, sep;
+ if (fixup_get_svalue(_m, (gparam_p)_subject, &subject) != 0) {
+ LM_ERR("cannot get subject value\n");
+ return -1;
+ } else {
+ if (subject.len == 0) {
+ LM_ERR("subject cannot be empty string\n");
+ return -1;
+ }
+ }
+
+ if (fixup_get_svalue(_m, (gparam_p)_list, &list) != 0) {
+ LM_ERR("cannot get list value\n");
+ return -1;
+ } else {
+ if (list.len == 0) return -1;
+ }
+ sep.s = _sep;
+ sep.len = 1;
+
+ return ki_in_list_prefix(_m, &subject, &list, &sep);
+}
+
static int cmp_str_f(struct sip_msg *msg, char *str1, char *str2 )
{
str s1;
@@ -4049,6 +4197,11 @@ static sr_kemi_t sr_kemi_textops_exports[] = {
{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
},
+ { str_init("textops"), str_init("in_list_prefix"),
+ SR_KEMIP_INT, ki_in_list_prefix,
+ { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
+ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+ },
{ str_init("textops"), str_init("cmp_str"),
SR_KEMIP_INT, ki_cmp_str,
{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,