From 5cdf195d709dc0235170961af2003b70bcc2ecb6 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 10 Jul 2018 09:56:02 +0200 Subject: [PATCH] textops: added replace_str(match, repl, mode) - replace a string with another in the message buffer after the first line. The parameter mode coltrols if first ("f") match or all ("a") should be replaced - alternative to replace() that avoids regexp overhead when bare string can be matched --- src/modules/textops/textops.c | 102 ++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/modules/textops/textops.c b/src/modules/textops/textops.c index b4b3de4e11c..c2c43ce284f 100644 --- a/src/modules/textops/textops.c +++ b/src/modules/textops/textops.c @@ -88,6 +88,7 @@ MODULE_VERSION static int search_body_f(struct sip_msg*, char*, char*); static int search_hf_f(struct sip_msg*, char*, char*, char*); static int replace_f(struct sip_msg*, char*, char*); +static int replace_str_f(struct sip_msg*, char*, char*, char*); static int replace_body_f(struct sip_msg*, char*, char*); static int replace_all_f(struct sip_msg*, char*, char*); static int replace_body_all_f(struct sip_msg*, char*, char*); @@ -178,6 +179,9 @@ static cmd_export_t cmds[]={ {"replace", (cmd_function)replace_f, 2, fixup_regexp_none, fixup_free_regexp_none, ANY_ROUTE}, + {"replace_str", (cmd_function)replace_str_f, 3, + fixup_spve_all, fixup_free_spve_all, + ANY_ROUTE}, {"replace_body", (cmd_function)replace_body_f, 2, fixup_regexp_none, fixup_free_regexp_none, ANY_ROUTE}, @@ -779,6 +783,99 @@ static int ki_replace(sip_msg_t* msg, str* sre, str* sval) return ret; } +static char *textops_strfind(str *mbuf, str *mkey) +{ + char *sp; + + // Sanity check + if(!(mbuf && mkey && mbuf->len >= mkey->len)) + return NULL; + + for(sp = mbuf->s; sp <= mbuf->s + mbuf->len - mkey->len; sp++) { + if(*sp == mkey->s[0] && strncmp(sp, mkey->s, mkey->len) == 0) { + return sp; + } + } + + return NULL; +} + +static int ki_replace_str(sip_msg_t* msg, str* mkey, str* rval, str *rmode) +{ + sr_lump_t* l; + char* s; + str mbuf; + char *mp; + char rpos; + + if(mkey==NULL || rval==NULL) { + return -1; + } + if(mkey->s==NULL || mkey->len<=0) { + return 1; + } + + if(rmode==NULL || rmode->s==NULL || rmode->s[0]=='f' || rmode->s[0]=='F') { + rpos = 'f'; + } else { + rpos = 'a'; + } + + mbuf.s = get_header(msg); + mbuf.len = msg->len - (mbuf.s - msg->buf); + + while((mp=textops_strfind(&mbuf, mkey))!=NULL) { + + if ((l=del_lump(msg, mp - msg->buf, mkey->len, 0))==0) { + return -1; + } + s=pkg_malloc(rval->len+1); + if (s==0){ + LM_ERR("memory allocation failure\n"); + return -1; + } + memcpy(s, rval->s, rval->len); + if (insert_new_lump_after(l, s, rval->len, 0)==0){ + LM_ERR("could not insert new lump\n"); + pkg_free(s); + return -1; + } + + if(rpos=='f') { + return 1; + } + + mbuf.s = mp + mkey->len; + mbuf.len = msg->len - (mbuf.s - msg->buf); + } + + return 1; +} + +static int replace_str_f(sip_msg_t* msg, char* pmkey, char* prval, char* prmode) +{ + str mkey; + str rval; + str rmode; + + if(fixup_get_svalue(msg, (gparam_t*)pmkey, &mkey)<0) { + LM_ERR("failed to get the matching string parameter\n"); + return -1; + } + + if(fixup_get_svalue(msg, (gparam_t*)prval, &rval)<0) { + LM_ERR("failed to get the replacement string parameter\n"); + return -1; + } + + if(fixup_get_svalue(msg, (gparam_t*)prmode, &rmode)<0) { + LM_ERR("failed to get the replacement mode parameter\n"); + return -1; + } + + return ki_replace_str(msg, &mkey, &rval, &rmode); +} + static int replace_body_helper(sip_msg_t* msg, regex_t *re, str *val) { struct lump* l; @@ -4243,6 +4340,11 @@ static sr_kemi_t sr_kemi_textops_exports[] = { { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } }, + { str_init("textops"), str_init("replace_str"), + SR_KEMIP_INT, ki_replace_str, + { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR, + SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } + }, { str_init("textops"), str_init("replace_all"), SR_KEMIP_INT, ki_replace_all, { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,