From 2cd6f16f9a377bf35a6f3f840dbedc5780897736 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Thu, 23 Sep 2021 09:25:43 +0200 Subject: [PATCH] posops: functions for getting the position by reverse search --- src/modules/posops/doc/posops_admin.xml | 60 +++++++++++- src/modules/posops/posops_mod.c | 121 ++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 1 deletion(-) diff --git a/src/modules/posops/doc/posops_admin.xml b/src/modules/posops/doc/posops_admin.xml index b0b67b117e8..c9284dad815 100644 --- a/src/modules/posops/doc/posops_admin.xml +++ b/src/modules/posops/doc/posops_admin.xml @@ -264,7 +264,7 @@ $var(idx) = pos_find_str("100", "kamailio"); -
+
<function moreinfo="none">pos_findi_str(idx, val)</function> @@ -289,6 +289,64 @@ $var(idx) = pos_find_str("100", "kamailio"); ... $var(idx) = pos_findi_str("100", "kamailio"); +... + + +
+
+ + <function moreinfo="none">pos_rfind_str(idx, val)</function> + + + Return the last position of the val in message buffer starting at idx + (reverse search). In case of not finding it or error, the return code + is negative. If val is at index 0, it returns the value specified + by modparam idx0. + + + The idx can be an integer value or a variable holding an integer. If + the value is negative, the position is counted from the end of the buffer. + + + The val can be a static string or variables. + + + This function can be used from ANY_ROUTE. + + + <function>pos_find_str()</function> usage + +... +$var(idx) = pos_rfind_str("100", "kamailio"); +... + + +
+
+ + <function moreinfo="none">pos_rfindi_str(idx, val)</function> + + + Return the last position of the val (matching case insensitive) in message + buffer starting at idx (reverse search). In case of not finding it + or error, the return code is negative. If val is at index 0, it + returns the value specified by modparam idx0. + + + The idx can be an integer value or a variable holding an integer. If + the value is negative, the position is counted from the end of the buffer. + + + The val can be a static string or variables. + + + This function can be used from ANY_ROUTE. + + + <function>pos_rfindi_str()</function> usage + +... +$var(idx) = pos_rfindi_str("100", "kamailio"); ... diff --git a/src/modules/posops/posops_mod.c b/src/modules/posops/posops_mod.c index 6e367c53aae..31209a49ce4 100644 --- a/src/modules/posops/posops_mod.c +++ b/src/modules/posops/posops_mod.c @@ -47,6 +47,8 @@ static int w_posops_pos_body_start(sip_msg_t* msg, char* p1, char* p2); static int w_posops_pos_body_end(sip_msg_t* msg, char* p1, char* p2); static int w_posops_pos_find_str(sip_msg_t* msg, char* p1idx, char* p2val); static int w_posops_pos_findi_str(sip_msg_t* msg, char* p1idx, char* p2val); +static int w_posops_pos_rfind_str(sip_msg_t* msg, char* p1idx, char* p2val); +static int w_posops_pos_rfindi_str(sip_msg_t* msg, char* p1idx, char* p2val); typedef struct posops_data { int ret; @@ -90,6 +92,10 @@ static cmd_export_t cmds[]={ fixup_free_igp_spve, ANY_ROUTE}, {"pos_findi_str", (cmd_function)w_posops_pos_findi_str, 2, fixup_igp_spve, fixup_free_igp_spve, ANY_ROUTE}, + {"pos_rfind_str", (cmd_function)w_posops_pos_rfind_str, 2, fixup_igp_spve, + fixup_free_igp_spve, ANY_ROUTE}, + {"pos_rfindi_str", (cmd_function)w_posops_pos_rfindi_str, 2, fixup_igp_spve, + fixup_free_igp_spve, ANY_ROUTE}, {0, 0, 0, 0, 0, 0} }; @@ -522,6 +528,111 @@ static int w_posops_pos_findi_str(sip_msg_t* msg, char* p1idx, char* p2val) return ki_posops_pos_findi_str(msg, idx, &val); } + + +/** + * + */ +static int ki_posops_pos_rfind_str(sip_msg_t *msg, int idx, str *val) +{ + char *p; + str text; + + if(val==NULL || val->s==NULL || val->len<=0) { + return -1; + } + if(idx<0) { + idx += msg->len; + } + if(idx<0 || idx > msg->len - val->len) { + return -1; + } + text.s = msg->buf + idx; + text.len = msg->len - idx; + p = str_rsearch(&text, val); + if(p==NULL) { + return -1; + } + + _posops_data.idx = (int)(p - msg->buf); + _posops_data.ret = (_posops_data.idx==0)?posops_idx0:_posops_data.idx; + + return _posops_data.ret; +} + +/** + * + */ +static int w_posops_pos_rfind_str(sip_msg_t* msg, char* p1idx, char* p2val) +{ + int idx = 0; + str val = STR_NULL; + + if(fixup_get_ivalue(msg, (gparam_t*)p1idx, &idx)!=0) { + LM_ERR("unable to get idx parameter\n"); + return -1; + } + + if(fixup_get_svalue(msg, (gparam_t*)p2val, &val)!=0) { + LM_ERR("unable to get val parameter\n"); + return -1; + } + + return ki_posops_pos_rfind_str(msg, idx, &val); +} + +/** + * + */ +static int ki_posops_pos_rfindi_str(sip_msg_t *msg, int idx, str *val) +{ + char *p; + str text; + + if(val==NULL || val->s==NULL || val->len<=0) { + return -1; + } + if(idx<0) { + idx += msg->len; + } + if(idx<0 || idx > msg->len - val->len) { + return -1; + } + + text.s = msg->buf + idx; + text.len = msg->len - idx; + p = str_rcasesearch(&text, val); + if(p==NULL) { + return -1; + } + + _posops_data.idx = (int)(p - msg->buf); + _posops_data.ret = (_posops_data.idx==0)?posops_idx0:_posops_data.idx; + + return _posops_data.ret; +} + +/** + * + */ +static int w_posops_pos_rfindi_str(sip_msg_t* msg, char* p1idx, char* p2val) +{ + int idx = 0; + str val = STR_NULL; + + if(fixup_get_ivalue(msg, (gparam_t*)p1idx, &idx)!=0) { + LM_ERR("unable to get idx parameter\n"); + return -1; + } + + if(fixup_get_svalue(msg, (gparam_t*)p2val, &val)!=0) { + LM_ERR("unable to get val parameter\n"); + return -1; + } + + return ki_posops_pos_rfindi_str(msg, idx, &val); +} + /** * */ @@ -614,6 +725,16 @@ static sr_kemi_t sr_kemi_posops_exports[] = { { SR_KEMIP_INT, SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } }, + { str_init("posops"), str_init("pos_rfind_str"), + SR_KEMIP_INT, ki_posops_pos_rfind_str, + { SR_KEMIP_INT, SR_KEMIP_STR, SR_KEMIP_NONE, + SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } + }, + { str_init("posops"), str_init("pos_rfindi_str"), + SR_KEMIP_INT, ki_posops_pos_rfindi_str, + { SR_KEMIP_INT, SR_KEMIP_STR, SR_KEMIP_NONE, + SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } + }, { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } } };