PKG_NAME:=kamailio
PKG_VERSION:=5.7.2
-PKG_RELEASE:=1
+PKG_RELEASE:=2
PKG_SOURCE_URL:=https://www.kamailio.org/pub/kamailio/$(PKG_VERSION)/src
PKG_SOURCE:=kamailio-$(PKG_VERSION)_src.tar.gz
$(eval $(call BuildKamailioModule,db_unixodbc,UnixODBC DB-backend,,+unixodbc))
$(eval $(call BuildKamailioModule,debugger,Interactive config file debugger,,))
$(eval $(call BuildKamailioModule,dialog,Dialog support,,+kamailio-mod-rr +kamailio-mod-tm))
-$(eval $(call BuildKamailioModule,dialplan,Dialplan management,,+libpcre))
+$(eval $(call BuildKamailioModule,dialplan,Dialplan management,,+libpcre2))
$(eval $(call BuildKamailioModule,dispatcher,Dispatcher,,))
$(eval $(call BuildKamailioModule,diversion,Diversion header insertion,,))
$(eval $(call BuildKamailioModule,dlgs,Track active calls in stateless mode,,))
$(eval $(call BuildKamailioModule,keepalive,SIP keepalive monitoring,,+kamailio-mod-tm,,))
$(eval $(call BuildKamailioModule,kemix,KEMI extensions,,,))
$(eval $(call BuildKamailioModule,kex,Core extensions,,))
-$(eval $(call BuildKamailioModule,lcr,Least Cost Routing,,+kamailio-mod-tm +libpcre))
+$(eval $(call BuildKamailioModule,lcr,Least Cost Routing,,+kamailio-mod-tm +libpcre2))
$(eval $(call BuildKamailioModule,ldap,LDAP connector,,+libopenldap))
$(eval $(call BuildKamailioModule,log_custom,Logging to custom backends,,))
$(eval $(call BuildKamailioModule,lost,HELD and LOST routing,,+kamailio-mod-http-client,))
$(eval $(call BuildKamailioModule,pv_headers,Flexible SIP header management,,))
$(eval $(call BuildKamailioModule,qos,QoS control,,+kamailio-mod-dialog))
$(eval $(call BuildKamailioModule,ratelimit,Traffic shapping,,))
-$(eval $(call BuildKamailioModule,regex,Regular Expression,,+libpcre))
+$(eval $(call BuildKamailioModule,regex,Regular Expression,,+libpcre2))
$(eval $(call BuildKamailioModule,registrar,SIP Registrar,,+kamailio-mod-usrloc))
$(eval $(call BuildKamailioModule,rls,Resource List Server,,+kamailio-mod-presence +kamailio-mod-pua +kamailio-mod-tm,))
$(eval $(call BuildKamailioModule,rr,Record-Route and Route,,))
--- /dev/null
+From 01d0d1de2c82db189c288a157932f4a3ba98970a Mon Sep 17 00:00:00 2001
+From: Victor Seva <linuxmaniac@torreviejawireless.org>
+Date: Wed, 17 May 2023 16:36:04 +0200
+Subject: [PATCH] dialplan: clang-format for coherent indentation and coding
+ style
+
+---
+ src/modules/dialplan/dialplan.c | 522 +++++++++++++++-----------------
+ src/modules/dialplan/dialplan.h | 89 +++---
+ src/modules/dialplan/dp_db.c | 364 +++++++++++-----------
+ src/modules/dialplan/dp_db.h | 38 +--
+ src/modules/dialplan/dp_repl.c | 387 +++++++++++------------
+ 5 files changed, 701 insertions(+), 699 deletions(-)
+
+--- a/src/modules/dialplan/dialplan.c
++++ b/src/modules/dialplan/dialplan.c
+@@ -35,8 +35,6 @@
+ */
+
+
+-
+-
+ #include <string.h>
+ #include <stdlib.h>
+ #include <stdio.h>
+@@ -67,18 +65,19 @@ static void mod_destroy();
+
+ static int dialplan_init_rpc(void);
+
+-static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2);
+-static int dp_trans_fixup(void ** param, int param_no);
+-static int dp_reload_f(struct sip_msg* msg);
+-static int w_dp_replace(sip_msg_t* msg, char* pid, char* psrc, char* pdst);
+-static int w_dp_match(sip_msg_t* msg, char* pid, char* psrc);
+-
+-static int ki_dp_translate(sip_msg_t* msg, int id, str *input, str *output);
+-static int ki_dp_translate_id(sip_msg_t* msg, int id);
+-static int ki_dp_translate_vars(sip_msg_t* msg, int id, str *input, str *output);
++static int dp_translate_f(struct sip_msg *msg, char *str1, char *str2);
++static int dp_trans_fixup(void **param, int param_no);
++static int dp_reload_f(struct sip_msg *msg);
++static int w_dp_replace(sip_msg_t *msg, char *pid, char *psrc, char *pdst);
++static int w_dp_match(sip_msg_t *msg, char *pid, char *psrc);
++
++static int ki_dp_translate(sip_msg_t *msg, int id, str *input, str *output);
++static int ki_dp_translate_id(sip_msg_t *msg, int id);
++static int ki_dp_translate_vars(
++ sip_msg_t *msg, int id, str *input, str *output);
+
+-int dp_replace_fixup(void** param, int param_no);
+-int dp_replace_fixup_free(void** param, int param_no);
++int dp_replace_fixup(void **param, int param_no);
++int dp_replace_fixup_free(void **param, int param_no);
+
+ str dp_attr_pvar_s = STR_NULL;
+ pv_spec_t *dp_attr_pvar = NULL;
+@@ -93,76 +92,69 @@ int dp_reload_delta = 5;
+
+ static time_t *dp_rpc_reload_time = NULL;
+
+-static param_export_t mod_params[]={
+- { "db_url", PARAM_STR, &dp_db_url },
+- { "table_name", PARAM_STR, &dp_table_name },
+- { "dpid_col", PARAM_STR, &dpid_column },
+- { "pr_col", PARAM_STR, &pr_column },
+- { "match_op_col", PARAM_STR, &match_op_column },
+- { "match_exp_col", PARAM_STR, &match_exp_column },
+- { "match_len_col", PARAM_STR, &match_len_column },
+- { "subst_exp_col", PARAM_STR, &subst_exp_column },
+- { "repl_exp_col", PARAM_STR, &repl_exp_column },
+- { "attrs_col", PARAM_STR, &attrs_column },
+- { "attrs_pvar", PARAM_STR, &dp_attr_pvar_s },
+- { "fetch_rows", PARAM_INT, &dp_fetch_rows },
+- { "match_dynamic", PARAM_INT, &dp_match_dynamic },
+- { "append_branch", PARAM_INT, &dp_append_branch },
+- { "reload_delta", PARAM_INT, &dp_reload_delta },
+- {0,0,0}
+-};
+-
+-static cmd_export_t cmds[]={
+- {"dp_translate",(cmd_function)dp_translate_f, 2, dp_trans_fixup, 0,
+- ANY_ROUTE},
+- {"dp_translate",(cmd_function)dp_translate_f, 1, dp_trans_fixup, 0,
+- ANY_ROUTE},
+- {"dp_reload",(cmd_function)dp_reload_f, 0, 0, 0,
+- ANY_ROUTE},
+- {"dp_match",(cmd_function)w_dp_match, 2, fixup_igp_spve,
+- fixup_free_igp_spve, ANY_ROUTE},
+- {"dp_replace",(cmd_function)w_dp_replace, 3, dp_replace_fixup,
+- dp_replace_fixup_free, ANY_ROUTE},
+- {0,0,0,0,0,0}
+-};
+-
+-struct module_exports exports= {
+- "dialplan", /* module's name */
+- DEFAULT_DLFLAGS, /* dlopen flags */
+- cmds, /* exported functions */
+- mod_params, /* param exports */
+- 0, /* exported RPC functions */
+- 0, /* exported pseudo-variables */
+- 0, /* reply processing function */
+- mod_init, /* module initialization function */
+- child_init, /* per-child init function */
+- mod_destroy /* module destroy function */
++static param_export_t mod_params[] = {{"db_url", PARAM_STR, &dp_db_url},
++ {"table_name", PARAM_STR, &dp_table_name},
++ {"dpid_col", PARAM_STR, &dpid_column},
++ {"pr_col", PARAM_STR, &pr_column},
++ {"match_op_col", PARAM_STR, &match_op_column},
++ {"match_exp_col", PARAM_STR, &match_exp_column},
++ {"match_len_col", PARAM_STR, &match_len_column},
++ {"subst_exp_col", PARAM_STR, &subst_exp_column},
++ {"repl_exp_col", PARAM_STR, &repl_exp_column},
++ {"attrs_col", PARAM_STR, &attrs_column},
++ {"attrs_pvar", PARAM_STR, &dp_attr_pvar_s},
++ {"fetch_rows", PARAM_INT, &dp_fetch_rows},
++ {"match_dynamic", PARAM_INT, &dp_match_dynamic},
++ {"append_branch", PARAM_INT, &dp_append_branch},
++ {"reload_delta", PARAM_INT, &dp_reload_delta}, {0, 0, 0}};
++
++static cmd_export_t cmds[] = {{"dp_translate", (cmd_function)dp_translate_f, 2,
++ dp_trans_fixup, 0, ANY_ROUTE},
++ {"dp_translate", (cmd_function)dp_translate_f, 1, dp_trans_fixup, 0,
++ ANY_ROUTE},
++ {"dp_reload", (cmd_function)dp_reload_f, 0, 0, 0, ANY_ROUTE},
++ {"dp_match", (cmd_function)w_dp_match, 2, fixup_igp_spve,
++ fixup_free_igp_spve, ANY_ROUTE},
++ {"dp_replace", (cmd_function)w_dp_replace, 3, dp_replace_fixup,
++ dp_replace_fixup_free, ANY_ROUTE},
++ {0, 0, 0, 0, 0, 0}};
++
++struct module_exports exports = {
++ "dialplan", /* module's name */
++ DEFAULT_DLFLAGS, /* dlopen flags */
++ cmds, /* exported functions */
++ mod_params, /* param exports */
++ 0, /* exported RPC functions */
++ 0, /* exported pseudo-variables */
++ 0, /* reply processing function */
++ mod_init, /* module initialization function */
++ child_init, /* per-child init function */
++ mod_destroy /* module destroy function */
+ };
+
+
+ static int mod_init(void)
+ {
+- if(dialplan_init_rpc()!=0)
+- {
++ if(dialplan_init_rpc() != 0) {
+ LM_ERR("failed to register RPC commands\n");
+ return -1;
+ }
+
+- LM_DBG("db_url=%s/%d/%p\n", ZSW(dp_db_url.s), dp_db_url.len,dp_db_url.s);
++ LM_DBG("db_url=%s/%d/%p\n", ZSW(dp_db_url.s), dp_db_url.len, dp_db_url.s);
+
+- if(dp_attr_pvar_s.s && dp_attr_pvar_s.len>0) {
++ if(dp_attr_pvar_s.s && dp_attr_pvar_s.len > 0) {
+ dp_attr_pvar = pv_cache_get(&dp_attr_pvar_s);
+- if( (dp_attr_pvar==NULL) ||
+- ((dp_attr_pvar->type != PVT_AVP) &&
+- (dp_attr_pvar->type != PVT_XAVP) &&
+- (dp_attr_pvar->type != PVT_SCRIPTVAR))) {
++ if((dp_attr_pvar == NULL)
++ || ((dp_attr_pvar->type != PVT_AVP)
++ && (dp_attr_pvar->type != PVT_XAVP)
++ && (dp_attr_pvar->type != PVT_SCRIPTVAR))) {
+ LM_ERR("invalid pvar name\n");
+ return -1;
+ }
+ }
+
+ dp_default_par2 = (dp_param_p)shm_malloc(sizeof(dp_param_t));
+- if(dp_default_par2 == NULL){
++ if(dp_default_par2 == NULL) {
+ LM_ERR("no shm more memory\n");
+ return -1;
+ }
+@@ -171,22 +163,22 @@ static int mod_init(void)
+ /* emulate "$rU/$rU" as second parameter for dp_translate() */
+ dp_default_param_s.len = strlen(dp_default_param_s.s);
+ dp_default_par2->v.sp[0] = pv_cache_get(&dp_default_param_s);
+- if (dp_default_par2->v.sp[0]==NULL) {
++ if(dp_default_par2->v.sp[0] == NULL) {
+ LM_ERR("input pv is invalid\n");
+ return -1;
+ }
+
+ dp_default_param_s.len = strlen(dp_default_param_s.s);
+ dp_default_par2->v.sp[1] = pv_cache_get(&dp_default_param_s);
+- if (dp_default_par2->v.sp[1]==NULL) {
++ if(dp_default_par2->v.sp[1] == NULL) {
+ LM_ERR("output pv is invalid\n");
+ return -1;
+ }
+
+- if(dp_fetch_rows<=0)
++ if(dp_fetch_rows <= 0)
+ dp_fetch_rows = 1000;
+
+- if(dp_reload_delta<0)
++ if(dp_reload_delta < 0)
+ dp_reload_delta = 5;
+
+ if(init_data() != 0) {
+@@ -214,11 +206,11 @@ static int child_init(int rank)
+ static void mod_destroy(void)
+ {
+ /*destroy shared memory*/
+- if(dp_default_par2){
++ if(dp_default_par2) {
+ shm_free(dp_default_par2);
+ dp_default_par2 = NULL;
+ }
+- if(dp_rpc_reload_time!=NULL) {
++ if(dp_rpc_reload_time != NULL) {
+ shm_free(dp_rpc_reload_time);
+ dp_rpc_reload_time = 0;
+ }
+@@ -226,20 +218,21 @@ static void mod_destroy(void)
+ }
+
+
+-static int dp_get_ivalue(struct sip_msg* msg, dp_param_p dp, int *val)
++static int dp_get_ivalue(struct sip_msg *msg, dp_param_p dp, int *val)
+ {
+ pv_value_t value;
+
+- if(dp->type==DP_VAL_INT) {
++ if(dp->type == DP_VAL_INT) {
+ *val = dp->v.id;
+ LM_DBG("dpid is %d from constant argument\n", *val);
+ return 0;
+ }
+
+- LM_DBG("searching %d\n",dp->v.sp[0]->type);
++ LM_DBG("searching %d\n", dp->v.sp[0]->type);
+
+- if( pv_get_spec_value( msg, dp->v.sp[0], &value)!=0
+- || value.flags&(PV_VAL_NULL|PV_VAL_EMPTY) || !(value.flags&PV_VAL_INT)) {
++ if(pv_get_spec_value(msg, dp->v.sp[0], &value) != 0
++ || value.flags & (PV_VAL_NULL | PV_VAL_EMPTY)
++ || !(value.flags & PV_VAL_INT)) {
+ LM_ERR("no AVP, XAVP or SCRIPTVAR found (error in scripts)\n");
+ return -1;
+ }
+@@ -249,14 +242,14 @@ static int dp_get_ivalue(struct sip_msg*
+ }
+
+
+-static int dp_get_svalue(struct sip_msg * msg, pv_spec_t *spec, str* val)
++static int dp_get_svalue(struct sip_msg *msg, pv_spec_t *spec, str *val)
+ {
+ pv_value_t value;
+
+ LM_DBG("searching %d \n", spec->type);
+
+- if ( pv_get_spec_value(msg,spec,&value)!=0 || value.flags&PV_VAL_NULL
+- || value.flags&PV_VAL_EMPTY || !(value.flags&PV_VAL_STR)){
++ if(pv_get_spec_value(msg, spec, &value) != 0 || value.flags & PV_VAL_NULL
++ || value.flags & PV_VAL_EMPTY || !(value.flags & PV_VAL_STR)) {
+ LM_ERR("no AVP, XAVP or SCRIPTVAR found (error in scripts)\n");
+ return -1;
+ }
+@@ -266,8 +259,8 @@ static int dp_get_svalue(struct sip_msg
+ }
+
+
+-static int dp_update(struct sip_msg * msg, pv_spec_t * dest,
+- str * repl, str * attrs)
++static int dp_update(
++ struct sip_msg *msg, pv_spec_t *dest, str *repl, str *attrs)
+ {
+ int no_change;
+ pv_value_t val;
+@@ -275,16 +268,16 @@ static int dp_update(struct sip_msg * ms
+ memset(&val, 0, sizeof(pv_value_t));
+ val.flags = PV_VAL_STR;
+
+- no_change = (dest==NULL) || (dest->type == PVT_NONE)
+- || (!repl->s) || (!repl->len);
++ no_change = (dest == NULL) || (dest->type == PVT_NONE) || (!repl->s)
++ || (!repl->len);
+
+- if (no_change)
++ if(no_change)
+ goto set_attr_pvar;
+
+ val.rs = *repl;
+
+ if(dest->setf) {
+- if(dest->setf(msg, &dest->pvp, (int)EQ_T, &val)<0) {
++ if(dest->setf(msg, &dest->pvp, (int)EQ_T, &val) < 0) {
+ LM_ERR("setting dst pseudo-variable failed\n");
+ return -1;
+ }
+@@ -292,7 +285,7 @@ static int dp_update(struct sip_msg * ms
+ LM_WARN("target variable is read only - skipping setting its value\n");
+ }
+
+- if(dp_append_branch!=0) {
++ if(dp_append_branch != 0) {
+ if(is_route_type(FAILURE_ROUTE)
+ && (dest->type == PVT_RURI
+ || dest->type == PVT_RURI_USERNAME)) {
+@@ -306,12 +299,11 @@ static int dp_update(struct sip_msg * ms
+
+ set_attr_pvar:
+
+- if(dp_attr_pvar==NULL || attrs==NULL)
++ if(dp_attr_pvar == NULL || attrs == NULL)
+ return 0;
+
+ val.rs = *attrs;
+- if(dp_attr_pvar->setf(msg, &dp_attr_pvar->pvp, (int)EQ_T, &val)<0)
+- {
++ if(dp_attr_pvar->setf(msg, &dp_attr_pvar->pvp, (int)EQ_T, &val) < 0) {
+ LM_ERR("setting attr pseudo-variable failed\n");
+ return -1;
+ }
+@@ -320,7 +312,7 @@ set_attr_pvar:
+ }
+
+
+-static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2)
++static int dp_translate_f(struct sip_msg *msg, char *str1, char *str2)
+ {
+ int dpid;
+ str input, output;
+@@ -332,59 +324,60 @@ static int dp_translate_f(struct sip_msg
+ return -1;
+
+ /*verify first param's value*/
+- id_par = (dp_param_p) str1;
+- if (dp_get_ivalue(msg, id_par, &dpid) != 0){
++ id_par = (dp_param_p)str1;
++ if(dp_get_ivalue(msg, id_par, &dpid) != 0) {
+ LM_ERR("no dpid value\n");
+ return -1;
+ }
+
+- if ((idp = select_dpid(dpid)) ==0 ){
++ if((idp = select_dpid(dpid)) == 0) {
+ LM_DBG("no information available for dpid %i\n", dpid);
+ return -2;
+ }
+
+- repl_par = (str2!=NULL)? ((dp_param_p)str2):dp_default_par2;
+- if (dp_get_svalue(msg, repl_par->v.sp[0], &input)!=0){
++ repl_par = (str2 != NULL) ? ((dp_param_p)str2) : dp_default_par2;
++ if(dp_get_svalue(msg, repl_par->v.sp[0], &input) != 0) {
+ LM_ERR("invalid param 2\n");
+ return -1;
+ }
+
+ LM_DBG("input is %.*s\n", input.len, input.s);
+
+- outattrs = (!dp_attr_pvar)?NULL:&attrs;
+- if (dp_translate_helper(msg, &input, &output, idp, outattrs)!=0) {
++ outattrs = (!dp_attr_pvar) ? NULL : &attrs;
++ if(dp_translate_helper(msg, &input, &output, idp, outattrs) != 0) {
+ LM_DBG("could not translate %.*s "
+- "with dpid %i\n", input.len, input.s, idp->dp_id);
++ "with dpid %i\n",
++ input.len, input.s, idp->dp_id);
+ return -1;
+ }
+- LM_DBG("input %.*s with dpid %i => output %.*s\n",
+- input.len, input.s, idp->dp_id, output.len, output.s);
++ LM_DBG("input %.*s with dpid %i => output %.*s\n", input.len, input.s,
++ idp->dp_id, output.len, output.s);
+
+ /* set the output */
+- if (dp_update(msg, repl_par->v.sp[1], &output, outattrs) !=0){
++ if(dp_update(msg, repl_par->v.sp[1], &output, outattrs) != 0) {
+ LM_ERR("cannot set the output\n");
+ return -1;
+ }
+
+ return 1;
+-
+ }
+
+-#define verify_par_type(_par_no, _spec, _ret) \
+- do{\
+- if( ((_par_no == 1) \
+- && (_spec->type != PVT_AVP) && (_spec->type != PVT_XAVP) && \
+- (_spec->type!=PVT_SCRIPTVAR) )\
+- ||((_par_no == 2) \
+- && (_spec->type != PVT_AVP) && (_spec->type != PVT_XAVP) && \
+- (_spec->type!=PVT_SCRIPTVAR) \
+- && (_spec->type!=PVT_RURI) && (_spec->type!=PVT_RURI_USERNAME))){\
+- \
+- LM_ERR("Unsupported Parameter TYPE[%d]\n", _spec->type);\
+- _ret = E_UNSPEC; \
+- goto error; \
+- }\
+- }while(0);
++#define verify_par_type(_par_no, _spec, _ret) \
++ do { \
++ if(((_par_no == 1) && (_spec->type != PVT_AVP) \
++ && (_spec->type != PVT_XAVP) \
++ && (_spec->type != PVT_SCRIPTVAR)) \
++ || ((_par_no == 2) && (_spec->type != PVT_AVP) \
++ && (_spec->type != PVT_XAVP) \
++ && (_spec->type != PVT_SCRIPTVAR) \
++ && (_spec->type != PVT_RURI) \
++ && (_spec->type != PVT_RURI_USERNAME))) { \
++ \
++ LM_ERR("Unsupported Parameter TYPE[%d]\n", _spec->type); \
++ _ret = E_UNSPEC; \
++ goto error; \
++ } \
++ } while(0);
+
+
+ /* first param: DPID: type: INT, AVP, XAVP, SVAR
+@@ -392,19 +385,20 @@ static int dp_translate_f(struct sip_msg
+ * second param: DST type: RURI, RURI_USERNAME, AVP, XAVP, SVAR, N/A
+ * default value for the second param: $ru.user/$ru.user
+ */
+-static int dp_trans_fixup(void ** param, int param_no){
++static int dp_trans_fixup(void **param, int param_no)
++{
+
+ int dpid;
+- dp_param_p dp_par= NULL;
+- char *p, *s=NULL;
++ dp_param_p dp_par = NULL;
++ char *p, *s = NULL;
+ str lstr;
+ int ret = E_INVALID_PARAMS;
+
+- if(param_no!=1 && param_no!=2)
++ if(param_no != 1 && param_no != 2)
+ return 0;
+
+- p = (char*)*param;
+- if(!p || (*p == '\0')){
++ p = (char *)*param;
++ if(!p || (*p == '\0')) {
+ LM_DBG("null param %i\n", param_no);
+ return E_CFG;
+ }
+@@ -412,7 +406,7 @@ static int dp_trans_fixup(void ** param,
+ LM_DBG("param_no is %i\n", param_no);
+
+ dp_par = (dp_param_p)pkg_malloc(sizeof(dp_param_t));
+- if(dp_par == NULL){
++ if(dp_par == NULL) {
+ LM_ERR("no more pkg memory\n");
+ return E_OUT_OF_MEM;
+ }
+@@ -421,19 +415,21 @@ static int dp_trans_fixup(void ** param,
+ if(param_no == 1) {
+ if(*p != '$') {
+ dp_par->type = DP_VAL_INT;
+- lstr.s = *param; lstr.len = strlen(*param);
++ lstr.s = *param;
++ lstr.len = strlen(*param);
+ if(str2sint(&lstr, &dpid) != 0) {
+- LM_ERR("bad number <%s>\n",(char *)(*param));
++ LM_ERR("bad number <%s>\n", (char *)(*param));
+ ret = E_CFG;
+ goto error;
+ }
+
+ dp_par->type = DP_VAL_INT;
+ dp_par->v.id = dpid;
+- }else{
+- lstr.s = p; lstr.len = strlen(p);
++ } else {
++ lstr.s = p;
++ lstr.len = strlen(p);
+ dp_par->v.sp[0] = pv_cache_get(&lstr);
+- if (dp_par->v.sp[0]==NULL) {
++ if(dp_par->v.sp[0] == NULL) {
+ goto error;
+ }
+
+@@ -442,30 +438,32 @@ static int dp_trans_fixup(void ** param,
+ }
+ } else {
+
+- if (((s = strchr(p, '/')) != 0) && (*(s+1)=='\0'))
++ if(((s = strchr(p, '/')) != 0) && (*(s + 1) == '\0'))
+ goto error;
+
+- if (s != 0) {
+- *s = '\0'; s++;
++ if(s != 0) {
++ *s = '\0';
++ s++;
+ }
+
+- lstr.s = p; lstr.len = strlen(p);
++ lstr.s = p;
++ lstr.len = strlen(p);
+ dp_par->v.sp[0] = pv_cache_get(&lstr);
+- if(dp_par->v.sp[0]==NULL) {
++ if(dp_par->v.sp[0] == NULL) {
+ goto error;
+ }
+
+- if (s != 0) {
+- lstr.s = s; lstr.len = strlen(s);
++ if(s != 0) {
++ lstr.s = s;
++ lstr.len = strlen(s);
+ dp_par->v.sp[1] = pv_cache_get(&lstr);
+- if (dp_par->v.sp[1]==NULL) {
++ if(dp_par->v.sp[1] == NULL) {
+ goto error;
+ }
+ verify_par_type(param_no, dp_par->v.sp[1], ret);
+ }
+
+ dp_par->type = DP_VAL_SPEC;
+-
+ }
+
+ *param = (void *)dp_par;
+@@ -474,13 +472,14 @@ static int dp_trans_fixup(void ** param,
+
+ error:
+ LM_ERR("failed to parse param %i\n", param_no);
+- if(dp_par) pkg_free(dp_par);
++ if(dp_par)
++ pkg_free(dp_par);
+
+ return ret;
+ }
+
+-static int dp_replace_helper(sip_msg_t *msg, int dpid, str *input,
+- pv_spec_t *pvd)
++static int dp_replace_helper(
++ sip_msg_t *msg, int dpid, str *input, pv_spec_t *pvd)
+ {
+ dpl_id_p idp;
+ str tmp = STR_NULL;
+@@ -488,25 +487,26 @@ static int dp_replace_helper(sip_msg_t *
+ str *output = NULL;
+ str *outattrs = NULL;
+
+- if ((idp = select_dpid(dpid)) ==0) {
++ if((idp = select_dpid(dpid)) == 0) {
+ LM_DBG("no information available for dpid %i\n", dpid);
+ return -2;
+ }
+
+- outattrs = (!dp_attr_pvar)?NULL:&attrs;
+- output = (!pvd)?NULL:&tmp;
+- if (dp_translate_helper(msg, input, output, idp, outattrs)!=0) {
++ outattrs = (!dp_attr_pvar) ? NULL : &attrs;
++ output = (!pvd) ? NULL : &tmp;
++ if(dp_translate_helper(msg, input, output, idp, outattrs) != 0) {
+ LM_DBG("could not translate %.*s "
+- "with dpid %i\n", input->len, input->s, idp->dp_id);
++ "with dpid %i\n",
++ input->len, input->s, idp->dp_id);
+ return -1;
+ }
+- if (output) {
+- LM_DBG("input %.*s with dpid %i => output %.*s\n",
+- input->len, input->s, idp->dp_id, output->len, output->s);
++ if(output) {
++ LM_DBG("input %.*s with dpid %i => output %.*s\n", input->len, input->s,
++ idp->dp_id, output->len, output->s);
+ }
+
+ /* set the output */
+- if (dp_update(msg, pvd, output, outattrs) !=0){
++ if(dp_update(msg, pvd, output, outattrs) != 0) {
+ LM_ERR("cannot set the output\n");
+ return -1;
+ }
+@@ -514,31 +514,31 @@ static int dp_replace_helper(sip_msg_t *
+ return 1;
+ }
+
+-static int w_dp_replace(sip_msg_t* msg, char* pid, char* psrc, char* pdst)
++static int w_dp_replace(sip_msg_t *msg, char *pid, char *psrc, char *pdst)
+ {
+ int dpid = 1;
+ str src = STR_NULL;
+ pv_spec_t *pvd = NULL;
+
+- if(fixup_get_ivalue(msg, (gparam_t*)pid, &dpid)<0) {
++ if(fixup_get_ivalue(msg, (gparam_t *)pid, &dpid) < 0) {
+ LM_ERR("failed to get dialplan id value\n");
+ return -1;
+ }
+- if(fixup_get_svalue(msg, (gparam_t*)psrc, &src)<0) {
++ if(fixup_get_svalue(msg, (gparam_t *)psrc, &src) < 0) {
+ LM_ERR("failed to get src value\n");
+ return -1;
+ }
+- pvd = (pv_spec_t*)pdst;
++ pvd = (pv_spec_t *)pdst;
+
+ return dp_replace_helper(msg, dpid, &src, pvd);
+ }
+
+-static int ki_dp_replace(sip_msg_t* msg, int dpid, str* src, str* dst)
++static int ki_dp_replace(sip_msg_t *msg, int dpid, str *src, str *dst)
+ {
+ pv_spec_t *pvd = NULL;
+
+ pvd = pv_cache_get(dst);
+- if(pvd==NULL) {
++ if(pvd == NULL) {
+ LM_ERR("cannot get pv spec for [%.*s]\n", dst->len, dst->s);
+ return -1;
+ }
+@@ -546,16 +546,16 @@ static int ki_dp_replace(sip_msg_t* msg,
+ return dp_replace_helper(msg, dpid, src, pvd);
+ }
+
+-static int w_dp_match(sip_msg_t* msg, char* pid, char* psrc)
++static int w_dp_match(sip_msg_t *msg, char *pid, char *psrc)
+ {
+ int dpid = 1;
+ str src = STR_NULL;
+
+- if(fixup_get_ivalue(msg, (gparam_t*)pid, &dpid)<0) {
++ if(fixup_get_ivalue(msg, (gparam_t *)pid, &dpid) < 0) {
+ LM_ERR("failed to get dialplan id value\n");
+ return -1;
+ }
+- if(fixup_get_svalue(msg, (gparam_t*)psrc, &src)<0) {
++ if(fixup_get_svalue(msg, (gparam_t *)psrc, &src) < 0) {
+ LM_ERR("failed to get src value\n");
+ return -1;
+ }
+@@ -563,30 +563,30 @@ static int w_dp_match(sip_msg_t* msg, ch
+ return dp_replace_helper(msg, dpid, &src, NULL);
+ }
+
+-static int ki_dp_match(sip_msg_t* msg, int dpid, str* src)
++static int ki_dp_match(sip_msg_t *msg, int dpid, str *src)
+ {
+ return dp_replace_helper(msg, dpid, src, NULL);
+ }
+
+-int dp_replace_fixup(void** param, int param_no)
++int dp_replace_fixup(void **param, int param_no)
+ {
+- if (param_no == 1)
++ if(param_no == 1)
+ return fixup_igp_null(param, param_no);
+- else if (param_no == 2)
++ else if(param_no == 2)
+ return fixup_spve_all(param, param_no);
+- else if (param_no == 3)
++ else if(param_no == 3)
+ return fixup_pvar_all(param, param_no);
+ return E_UNSPEC;
+ }
+
+
+-int dp_replace_fixup_free(void** param, int param_no)
++int dp_replace_fixup_free(void **param, int param_no)
+ {
+- if (param_no == 1)
++ if(param_no == 1)
+ return fixup_free_igp_null(param, param_no);
+- else if (param_no == 2)
++ else if(param_no == 2)
+ return fixup_free_spve_all(param, param_no);
+- else if (param_no == 3)
++ else if(param_no == 3)
+ return fixup_free_pvar_all(param, param_no);
+ return E_UNSPEC;
+ }
+@@ -594,14 +594,14 @@ int dp_replace_fixup_free(void** param,
+ /**
+ * trigger reload of dialplan db records from config file
+ */
+-static int dp_reload_f(struct sip_msg* msg)
++static int dp_reload_f(struct sip_msg *msg)
+ {
+- if (dp_connect_db() < 0) {
++ if(dp_connect_db() < 0) {
+ LM_ERR("failed to reload rules fron database (db connect)\n");
+ return -1;
+ }
+
+- if(dp_load_db() != 0){
++ if(dp_load_db() != 0) {
+ LM_ERR("failed to reload rules fron database (db load)\n");
+ dp_disconnect_db();
+ return -1;
+@@ -614,35 +614,34 @@ static int dp_reload_f(struct sip_msg* m
+ }
+
+
+-static const char* dialplan_rpc_reload_doc[2] = {
+- "Reload dialplan table from database",
+- 0
+-};
++static const char *dialplan_rpc_reload_doc[2] = {
++ "Reload dialplan table from database", 0};
+
+
+ /*
+ * RPC command to reload dialplan table
+ */
+-static void dialplan_rpc_reload(rpc_t* rpc, void* ctx)
++static void dialplan_rpc_reload(rpc_t *rpc, void *ctx)
+ {
+- if(dp_rpc_reload_time==NULL) {
++ if(dp_rpc_reload_time == NULL) {
+ LM_ERR("not ready for reload\n");
+ rpc->fault(ctx, 500, "Not ready for reload");
+ return;
+ }
+- if(*dp_rpc_reload_time!=0 && *dp_rpc_reload_time > time(NULL) - dp_reload_delta) {
++ if(*dp_rpc_reload_time != 0
++ && *dp_rpc_reload_time > time(NULL) - dp_reload_delta) {
+ LM_ERR("ongoing reload\n");
+ rpc->fault(ctx, 500, "ongoing reload");
+ return;
+ }
+ *dp_rpc_reload_time = time(NULL);
+- if (dp_connect_db() < 0) {
++ if(dp_connect_db() < 0) {
+ LM_ERR("failed to reload rules fron database (db connect)\n");
+ rpc->fault(ctx, 500, "DB Connection Error");
+ return;
+ }
+
+- if(dp_load_db() != 0){
++ if(dp_load_db() != 0) {
+ LM_ERR("failed to reload rules fron database (db load)\n");
+ dp_disconnect_db();
+ rpc->fault(ctx, 500, "Dialplan Reload Failed");
+@@ -654,63 +653,55 @@ static void dialplan_rpc_reload(rpc_t* r
+ }
+
+
+-
+-static const char* dialplan_rpc_translate_doc[2] = {
+- "Perform dialplan translation",
+- 0
+-};
++static const char *dialplan_rpc_translate_doc[2] = {
++ "Perform dialplan translation", 0};
+
+
+ /*
+ * RPC command to perform dialplan translation
+ */
+-static void dialplan_rpc_translate(rpc_t* rpc, void* ctx)
++static void dialplan_rpc_translate(rpc_t *rpc, void *ctx)
+ {
+ dpl_id_p idp;
+ str input;
+ int dpid;
+- str attrs = {"", 0};
++ str attrs = {"", 0};
+ str output = {0, 0};
+- void* th;
++ void *th;
+
+- if (rpc->scan(ctx, "dS", &dpid, &input) < 2)
+- {
++ if(rpc->scan(ctx, "dS", &dpid, &input) < 2) {
+ rpc->fault(ctx, 500, "Invalid parameters");
+ return;
+ }
+
+- if ((idp = select_dpid(dpid)) == 0 ){
++ if((idp = select_dpid(dpid)) == 0) {
+ LM_ERR("no information available for dpid %i\n", dpid);
+ rpc->fault(ctx, 500, "Dialplan ID not matched");
+ return;
+ }
+
+- if(input.s == NULL || input.len== 0) {
++ if(input.s == NULL || input.len == 0) {
+ LM_ERR("empty input parameter\n");
+ rpc->fault(ctx, 500, "Empty input parameter");
+ return;
+ }
+
+- LM_DBG("trying to translate %.*s with dpid %i\n",
+- input.len, input.s, idp->dp_id);
+- if (dp_translate_helper(NULL, &input, &output, idp, &attrs)!=0){
+- LM_DBG("could not translate %.*s with dpid %i\n",
+- input.len, input.s, idp->dp_id);
++ LM_DBG("trying to translate %.*s with dpid %i\n", input.len, input.s,
++ idp->dp_id);
++ if(dp_translate_helper(NULL, &input, &output, idp, &attrs) != 0) {
++ LM_DBG("could not translate %.*s with dpid %i\n", input.len, input.s,
++ idp->dp_id);
+ rpc->fault(ctx, 500, "No translation");
+ return;
+ }
+- LM_DBG("input %.*s with dpid %i => output %.*s\n",
+- input.len, input.s, idp->dp_id, output.len, output.s);
++ LM_DBG("input %.*s with dpid %i => output %.*s\n", input.len, input.s,
++ idp->dp_id, output.len, output.s);
+
+- if (rpc->add(ctx, "{", &th) < 0)
+- {
++ if(rpc->add(ctx, "{", &th) < 0) {
+ rpc->fault(ctx, 500, "Internal error creating rpc");
+ return;
+ }
+- if(rpc->struct_add(th, "SS",
+- "Output", &output,
+- "Attributes", &attrs)<0)
+- {
++ if(rpc->struct_add(th, "SS", "Output", &output, "Attributes", &attrs) < 0) {
+ rpc->fault(ctx, 500, "Internal error creating rpc");
+ return;
+ }
+@@ -721,23 +712,22 @@ static void dialplan_rpc_translate(rpc_t
+ /*
+ * RPC command to dump dialplan
+ */
+-static void dialplan_rpc_dump(rpc_t* rpc, void* ctx)
++static void dialplan_rpc_dump(rpc_t *rpc, void *ctx)
+ {
+ dpl_id_p idp;
+ dpl_index_p indexp;
+ dpl_node_p rulep;
+ int dpid;
+- void* th;
+- void* ih;
+- void* sh;
++ void *th;
++ void *ih;
++ void *sh;
+
+- if (rpc->scan(ctx, "d", &dpid) < 1)
+- {
++ if(rpc->scan(ctx, "d", &dpid) < 1) {
+ rpc->fault(ctx, 500, "Missing parameter");
+ return;
+ }
+
+- if ((idp = select_dpid(dpid)) == 0 ) {
++ if((idp = select_dpid(dpid)) == 0) {
+ LM_ERR("no information available for dpid %i\n", dpid);
+ rpc->fault(ctx, 500, "Dialplan ID not matched");
+ return;
+@@ -746,58 +736,49 @@ static void dialplan_rpc_dump(rpc_t* rpc
+ LM_DBG("trying to dump dpid %i\n", idp->dp_id);
+
+ /* add entry node */
+- if (rpc->add(ctx, "{", &th) < 0)
+- {
++ if(rpc->add(ctx, "{", &th) < 0) {
+ rpc->fault(ctx, 500, "Internal error root reply");
+ return;
+ }
+
+- if(rpc->struct_add(th, "d[",
+- "DPID", dpid,
+- "ENTRIES", &ih)<0)
+- {
++ if(rpc->struct_add(th, "d[", "DPID", dpid, "ENTRIES", &ih) < 0) {
+ rpc->fault(ctx, 500, "Internal error sets structure");
+ return;
+ }
+
+- for(indexp=idp->first_index; indexp!=NULL;indexp=indexp->next) {
++ for(indexp = idp->first_index; indexp != NULL; indexp = indexp->next) {
+ LM_DBG("INDEX LEN: %i\n", indexp->len);
+- for(rulep = indexp->first_rule; rulep!= NULL;rulep = rulep->next) {
++ for(rulep = indexp->first_rule; rulep != NULL; rulep = rulep->next) {
+ LM_DBG("DPID: %i PRIO : %i\n", rulep->dpid, rulep->pr);
+- if (rpc->struct_add(ih, "{","ENTRY", &sh) < 0)
+- {
++ if(rpc->struct_add(ih, "{", "ENTRY", &sh) < 0) {
+ rpc->fault(ctx, 500, "Internal error root reply");
+ return;
+ }
+
+- if (rpc->struct_add(sh, "dd", "PRIO", rulep->pr,
+- "MATCHOP", rulep->matchop)<0)
+- {
++ if(rpc->struct_add(
++ sh, "dd", "PRIO", rulep->pr, "MATCHOP", rulep->matchop)
++ < 0) {
+ rpc->fault(ctx, 500, "Internal error adding prio");
+ return;
+ }
+- if (rpc->struct_add(sh, "s", "MATCHEXP", rulep->match_exp) < 0 )
+- {
++ if(rpc->struct_add(sh, "s", "MATCHEXP", rulep->match_exp) < 0) {
+ rpc->fault(ctx, 500, "Internal error adding match exp");
+ return;
+ }
+- if (rpc->struct_add(sh, "d", "MATCHLEN", rulep->matchlen) < 0 )
+- {
+- rpc->fault(ctx, 500, "Internal error adding expression data and attribute");
++ if(rpc->struct_add(sh, "d", "MATCHLEN", rulep->matchlen) < 0) {
++ rpc->fault(ctx, 500,
++ "Internal error adding expression data and attribute");
+ return;
+ }
+- if (rpc->struct_add(sh, "s", "SUBSTEXP", rulep->subst_exp) < 0 )
+- {
++ if(rpc->struct_add(sh, "s", "SUBSTEXP", rulep->subst_exp) < 0) {
+ rpc->fault(ctx, 500, "Internal error adding subst exp");
+ return;
+ }
+- if (rpc->struct_add(sh, "s", "REPLEXP", rulep->repl_exp) < 0 )
+- {
++ if(rpc->struct_add(sh, "s", "REPLEXP", rulep->repl_exp) < 0) {
+ rpc->fault(ctx, 500, "Internal error adding replace exp ");
+ return;
+ }
+- if (rpc->struct_add(sh, "s", "ATTRS", rulep->attrs) < 0 )
+- {
++ if(rpc->struct_add(sh, "s", "ATTRS", rulep->attrs) < 0) {
+ rpc->fault(ctx, 500, "Internal error adding attribute");
+ return;
+ }
+@@ -807,26 +788,19 @@ static void dialplan_rpc_dump(rpc_t* rpc
+ return;
+ }
+
+-static const char* dialplan_rpc_dump_doc[2] = {
+- "Dump dialplan content",
+- 0
+-};
++static const char *dialplan_rpc_dump_doc[2] = {"Dump dialplan content", 0};
+
+
+ rpc_export_t dialplan_rpc_list[] = {
+- {"dialplan.reload", dialplan_rpc_reload,
+- dialplan_rpc_reload_doc, 0},
+- {"dialplan.translate", dialplan_rpc_translate,
+- dialplan_rpc_translate_doc, 0},
+- {"dialplan.dump", dialplan_rpc_dump,
+- dialplan_rpc_dump_doc, 0},
+- {0, 0, 0, 0}
+-};
++ {"dialplan.reload", dialplan_rpc_reload, dialplan_rpc_reload_doc, 0},
++ {"dialplan.translate", dialplan_rpc_translate,
++ dialplan_rpc_translate_doc, 0},
++ {"dialplan.dump", dialplan_rpc_dump, dialplan_rpc_dump_doc, 0},
++ {0, 0, 0, 0}};
+
+ static int dialplan_init_rpc(void)
+ {
+- if (rpc_register_array(dialplan_rpc_list)!=0)
+- {
++ if(rpc_register_array(dialplan_rpc_list) != 0) {
+ LM_ERR("failed to register RPC commands\n");
+ return -1;
+ }
+@@ -863,20 +837,22 @@ static sr_kemi_t sr_kemi_dialplan_export
+ };
+ /* clang-format on */
+
+-static int ki_dp_translate(sip_msg_t* msg, int id, str *input_spv, str *output_spv) {
++static int ki_dp_translate(
++ sip_msg_t *msg, int id, str *input_spv, str *output_spv)
++{
+ str input, output;
+ dpl_id_p idp;
+ str attrs, *outattrs;
+ pv_spec_t *pvs_i = NULL, *pvs_o = NULL;
+
+- if (!msg)
++ if(!msg)
+ return -1;
+
+- if (input_spv != NULL && (input_spv->s == NULL || input_spv->len <= 0)) {
++ if(input_spv != NULL && (input_spv->s == NULL || input_spv->len <= 0)) {
+ LM_ERR("invalid destination var name for input\n");
+ return -1;
+ }
+- if (output_spv != NULL && (output_spv->s == NULL || output_spv->len <= 0)) {
++ if(output_spv != NULL && (output_spv->s == NULL || output_spv->len <= 0)) {
+ LM_ERR("invalid destination var name for output\n");
+ return -1;
+ }
+@@ -892,56 +868,60 @@ static int ki_dp_translate(sip_msg_t* ms
+ pvs_o = pv_cache_get(output_spv);
+ }
+
+- if (pvs_i == NULL || pvs_o == NULL) {
++ if(pvs_i == NULL || pvs_o == NULL) {
+ LM_ERR("cannot get pv spec for input or output\n");
+ return -1;
+ }
+
+- if ((pvs_i->type!=PVT_AVP && pvs_i->type!=PVT_XAVP && pvs_i->type!=PVT_SCRIPTVAR &&
+- pvs_i->type!=PVT_RURI && pvs_i->type!=PVT_RURI_USERNAME) ||
+- (pvs_o->type!=PVT_AVP && pvs_o->type!=PVT_XAVP && pvs_o->type!=PVT_SCRIPTVAR &&
+- pvs_o->type!=PVT_RURI && pvs_o->type!=PVT_RURI_USERNAME)) {
++ if((pvs_i->type != PVT_AVP && pvs_i->type != PVT_XAVP
++ && pvs_i->type != PVT_SCRIPTVAR && pvs_i->type != PVT_RURI
++ && pvs_i->type != PVT_RURI_USERNAME)
++ || (pvs_o->type != PVT_AVP && pvs_o->type != PVT_XAVP
++ && pvs_o->type != PVT_SCRIPTVAR && pvs_o->type != PVT_RURI
++ && pvs_o->type != PVT_RURI_USERNAME)) {
+ LM_ERR("type of pv error\n");
+ return -1;
+ }
+
+- if ((idp = select_dpid(id)) ==0 ){
++ if((idp = select_dpid(id)) == 0) {
+ LM_DBG("no information available for dpid %i\n", id);
+ return -2;
+ }
+
+ /* get the input */
+- if (dp_get_svalue(msg, pvs_i, &input)!=0){
++ if(dp_get_svalue(msg, pvs_i, &input) != 0) {
+ LM_ERR("invalid param 2\n");
+ return -1;
+ }
+
+ LM_DBG("input is %.*s\n", input.len, input.s);
+
+- outattrs = (!dp_attr_pvar)?NULL:&attrs;
+- if (dp_translate_helper(msg, &input, &output, idp, outattrs)!=0) {
++ outattrs = (!dp_attr_pvar) ? NULL : &attrs;
++ if(dp_translate_helper(msg, &input, &output, idp, outattrs) != 0) {
+ LM_DBG("could not translate %.*s "
+- "with dpid %i\n", input.len, input.s, idp->dp_id);
++ "with dpid %i\n",
++ input.len, input.s, idp->dp_id);
+ return -1;
+ }
+- LM_DBG("input %.*s with dpid %i => output %.*s\n",
+- input.len, input.s, idp->dp_id, output.len, output.s);
++ LM_DBG("input %.*s with dpid %i => output %.*s\n", input.len, input.s,
++ idp->dp_id, output.len, output.s);
+
+ /* set the output */
+- if (dp_update(msg, pvs_o, &output, outattrs) !=0){
++ if(dp_update(msg, pvs_o, &output, outattrs) != 0) {
+ LM_ERR("cannot set the output\n");
+ return -1;
+ }
+
+ return 1;
+-
+ }
+
+-static int ki_dp_translate_id(sip_msg_t* msg, int id) {
++static int ki_dp_translate_id(sip_msg_t *msg, int id)
++{
+ return ki_dp_translate(msg, id, NULL, NULL);
+ }
+
+-static int ki_dp_translate_vars(sip_msg_t* msg, int id, str *input, str *output) {
++static int ki_dp_translate_vars(sip_msg_t *msg, int id, str *input, str *output)
++{
+ return ki_dp_translate(msg, id, input, output);
+ }
+
+--- a/src/modules/dialplan/dialplan.h
++++ b/src/modules/dialplan/dialplan.h
+@@ -34,59 +34,64 @@
+ #include "../../core/pvar.h"
+ #include "../../core/parser/msg_parser.h"
+
+-#define DP_EQUAL_OP 0
+-#define DP_REGEX_OP 1
+-#define DP_FNMATCH_OP 2
+-
+-#define MAX_REPLACE_WITH 10
+-
+-#define DP_TFLAGS_PV_MATCH (1 << 0)
+-#define DP_TFLAGS_PV_SUBST (1 << 1)
+-
+-typedef struct dpl_node {
+- int dpid; /* dialplan id */
+- int pr; /* priority */
+- int matchop; /* matching operator */
+- int matchlen; /* matching value length */
+- str match_exp; /* match-first string */
+- str subst_exp; /* match string with subtitution groupping */
+- str repl_exp; /* replacement expression string */
+- pcre *match_comp; /* compiled matching expression */
+- pcre *subst_comp; /* compiled substitution expression */
++#define DP_EQUAL_OP 0
++#define DP_REGEX_OP 1
++#define DP_FNMATCH_OP 2
++
++#define MAX_REPLACE_WITH 10
++
++#define DP_TFLAGS_PV_MATCH (1 << 0)
++#define DP_TFLAGS_PV_SUBST (1 << 1)
++
++typedef struct dpl_node
++{
++ int dpid; /* dialplan id */
++ int pr; /* priority */
++ int matchop; /* matching operator */
++ int matchlen; /* matching value length */
++ str match_exp; /* match-first string */
++ str subst_exp; /* match string with subtitution groupping */
++ str repl_exp; /* replacement expression string */
++ pcre *match_comp; /* compiled matching expression */
++ pcre *subst_comp; /* compiled substitution expression */
+ struct subst_expr *repl_comp; /* compiled replacement */
+- str attrs; /* attributes string */
+- unsigned int tflags; /* flags for type of values for matching */
++ str attrs; /* attributes string */
++ unsigned int tflags; /* flags for type of values for matching */
+
+- struct dpl_node * next; /* next rule */
++ struct dpl_node *next; /* next rule */
+ } dpl_node_t, *dpl_node_p;
+
+ /*For every distinct length of a matching string*/
+-typedef struct dpl_index{
++typedef struct dpl_index
++{
+ int len;
+- dpl_node_t * first_rule;
+- dpl_node_t * last_rule;
++ dpl_node_t *first_rule;
++ dpl_node_t *last_rule;
+
+- struct dpl_index * next;
+-}dpl_index_t, *dpl_index_p;
++ struct dpl_index *next;
++} dpl_index_t, *dpl_index_p;
+
+ /*For every DPID*/
+-typedef struct dpl_id{
++typedef struct dpl_id
++{
+ int dp_id;
+- dpl_index_t* first_index;/*fast access :rules with specific length*/
+- struct dpl_id * next;
+-}dpl_id_t,*dpl_id_p;
++ dpl_index_t *first_index; /*fast access :rules with specific length*/
++ struct dpl_id *next;
++} dpl_id_t, *dpl_id_p;
+
+
+-#define DP_VAL_INT 0
+-#define DP_VAL_SPEC 1
++#define DP_VAL_INT 0
++#define DP_VAL_SPEC 1
+
+-typedef struct dp_param{
++typedef struct dp_param
++{
+ int type;
+- union {
++ union
++ {
+ int id;
+- pv_spec_t* sp[2];
++ pv_spec_t *sp[2];
+ } v;
+-}dp_param_t, *dp_param_p;
++} dp_param_t, *dp_param_p;
+
+ int init_data();
+ void destroy_data();
+@@ -94,12 +99,12 @@ int dp_load_db();
+
+ dpl_id_p select_dpid(int id);
+
+-struct subst_expr* repl_exp_parse(str subst);
++struct subst_expr *repl_exp_parse(str subst);
+ void repl_expr_free(struct subst_expr *se);
+-int dp_translate_helper(sip_msg_t *msg, str *user_name, str *repl_user,
+- dpl_id_p idp, str *);
+-int rule_translate(sip_msg_t *msg, str *instr, dpl_node_t *rule,
+- pcre *subst_comp, str *);
++int dp_translate_helper(
++ sip_msg_t *msg, str *user_name, str *repl_user, dpl_id_p idp, str *);
++int rule_translate(
++ sip_msg_t *msg, str *instr, dpl_node_t *rule, pcre *subst_comp, str *);
+
+ pcre *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype);
+ #endif
+--- a/src/modules/dialplan/dp_db.c
++++ b/src/modules/dialplan/dp_db.c
+@@ -37,45 +37,46 @@
+ #include "dp_db.h"
+ #include "dialplan.h"
+
+-str dp_db_url = str_init(DEFAULT_RODB_URL);
+-str dp_table_name = str_init(DP_TABLE_NAME);
+-str dpid_column = str_init(DPID_COL);
+-str pr_column = str_init(PR_COL);
+-str match_op_column = str_init(MATCH_OP_COL);
+-str match_exp_column= str_init(MATCH_EXP_COL);
+-str match_len_column= str_init(MATCH_LEN_COL);
+-str subst_exp_column= str_init(SUBST_EXP_COL);
+-str repl_exp_column = str_init(REPL_EXP_COL);
+-str attrs_column = str_init(ATTRS_COL);
++str dp_db_url = str_init(DEFAULT_RODB_URL);
++str dp_table_name = str_init(DP_TABLE_NAME);
++str dpid_column = str_init(DPID_COL);
++str pr_column = str_init(PR_COL);
++str match_op_column = str_init(MATCH_OP_COL);
++str match_exp_column = str_init(MATCH_EXP_COL);
++str match_len_column = str_init(MATCH_LEN_COL);
++str subst_exp_column = str_init(SUBST_EXP_COL);
++str repl_exp_column = str_init(REPL_EXP_COL);
++str attrs_column = str_init(ATTRS_COL);
+
+ extern int dp_fetch_rows;
+ extern int dp_match_dynamic;
+
+-static db1_con_t* dp_db_handle = 0; /* database connection handle */
++static db1_con_t *dp_db_handle = 0; /* database connection handle */
+ static db_func_t dp_dbf;
+
+-#define GET_STR_VALUE(_res, _values, _index)\
+- do{\
+- if ( VAL_NULL((_values)+ (_index)) ) { \
+- LM_ERR(" values %d is NULL - not allowed\n",_index);\
+- (_res).s = 0; (_res).len = 0;\
+- goto err;\
+- } \
+- (_res).s = VAL_STR((_values)+ (_index)).s;\
+- (_res).len = strlen(VAL_STR((_values)+ (_index)).s);\
+- }while(0);
++#define GET_STR_VALUE(_res, _values, _index) \
++ do { \
++ if(VAL_NULL((_values) + (_index))) { \
++ LM_ERR(" values %d is NULL - not allowed\n", _index); \
++ (_res).s = 0; \
++ (_res).len = 0; \
++ goto err; \
++ } \
++ (_res).s = VAL_STR((_values) + (_index)).s; \
++ (_res).len = strlen(VAL_STR((_values) + (_index)).s); \
++ } while(0);
+
+-void destroy_rule(dpl_node_t * rule);
++void destroy_rule(dpl_node_t *rule);
+ void destroy_hash(int);
+
+-dpl_node_t * build_rule(db_val_t * values);
++dpl_node_t *build_rule(db_val_t *values);
+ int add_rule2hash(dpl_node_t *, int);
+
+-void list_rule(dpl_node_t * );
++void list_rule(dpl_node_t *);
+ void list_hash(int h_index);
+
+
+-static dpl_id_p* dp_rules_hash = NULL;
++static dpl_id_p *dp_rules_hash = NULL;
+ static int *dp_crt_idx = NULL;
+ static int *dp_next_idx = NULL;
+
+@@ -91,7 +92,7 @@ int dpl_check_pv(str *in)
+ str s;
+ int len;
+
+- if(in==NULL || in->s==NULL)
++ if(in == NULL || in->s == NULL)
+ return -1;
+
+ LM_DBG("parsing [%.*s]\n", in->len, in->s);
+@@ -101,26 +102,27 @@ int dpl_check_pv(str *in)
+
+ p = in->s;
+
+- while(is_in_str(p,in))
+- {
+- while(is_in_str(p,in) && *p!=PV_MARKER)
++ while(is_in_str(p, in)) {
++ while(is_in_str(p, in) && *p != PV_MARKER)
+ p++;
+- if(*p == '\0' || !is_in_str(p,in))
++ if(*p == '\0' || !is_in_str(p, in))
+ break;
+ /* last char is $ ? */
+- if(!is_in_str(p+1, in))
++ if(!is_in_str(p + 1, in))
+ break;
+ s.s = p;
+- s.len = in->s+in->len-p;
++ s.len = in->s + in->len - p;
+ len = 0;
+ spec = pv_spec_lookup(&s, &len);
+- if(spec!=NULL) {
++ if(spec != NULL) {
+ /* found a variable */
+ LM_DBG("string [%.*s] has variables\n", in->len, in->s);
+ return 0;
+ }
+- if(len) p += len;
+- else p++;
++ if(len)
++ p += len;
++ else
++ p++;
+ }
+
+ /* not found */
+@@ -129,27 +131,28 @@ int dpl_check_pv(str *in)
+
+ int init_db_data(void)
+ {
+- if(!dp_table_name.s || dp_table_name.len<=0){
++ if(!dp_table_name.s || dp_table_name.len <= 0) {
+ LM_ERR("invalid database table name\n");
+ return -1;
+ }
+
+ /* Find a database module */
+- if (db_bind_mod(&dp_db_url, &dp_dbf) < 0){
++ if(db_bind_mod(&dp_db_url, &dp_dbf) < 0) {
+ LM_ERR("unable to bind to a database driver\n");
+ return -1;
+ }
+
+- if(dp_connect_db() !=0)
++ if(dp_connect_db() != 0)
+ return -1;
+
+- if(db_check_table_version(&dp_dbf, dp_db_handle, &dp_table_name,
+- DP_TABLE_VERSION) < 0) {
++ if(db_check_table_version(
++ &dp_dbf, dp_db_handle, &dp_table_name, DP_TABLE_VERSION)
++ < 0) {
+ DB_TABLE_VERSION_ERROR(dp_table_name);
+ goto error;
+ }
+
+- if(dp_load_db() != 0){
++ if(dp_load_db() != 0) {
+ LM_ERR("failed to load database data\n");
+ goto error;
+ }
+@@ -166,17 +169,17 @@ error:
+
+ int dp_connect_db(void)
+ {
+- if (dp_dbf.init==0){
++ if(dp_dbf.init == 0) {
+ LM_CRIT("null dp_dbf\n");
+ return -1;
+ }
+
+- if(dp_db_handle){
++ if(dp_db_handle) {
+ LM_CRIT("BUG: connection to database already open\n");
+ return -1;
+ }
+
+- if ((dp_db_handle = dp_dbf.init(&dp_db_url)) == 0){
++ if((dp_db_handle = dp_dbf.init(&dp_db_url)) == 0) {
+ LM_ERR("unable to connect to the database\n");
+ return -1;
+ }
+@@ -187,7 +190,7 @@ int dp_connect_db(void)
+
+ void dp_disconnect_db(void)
+ {
+- if(dp_db_handle){
++ if(dp_db_handle) {
+ dp_dbf.close(dp_db_handle);
+ dp_db_handle = 0;
+ }
+@@ -198,20 +201,20 @@ int init_data(void)
+ {
+ int *p;
+
+- dp_rules_hash = (dpl_id_p *)shm_malloc(2*sizeof(dpl_id_p));
++ dp_rules_hash = (dpl_id_p *)shm_malloc(2 * sizeof(dpl_id_p));
+ if(!dp_rules_hash) {
+ LM_ERR("out of shm memory\n");
+ return -1;
+ }
+ dp_rules_hash[0] = dp_rules_hash[1] = 0;
+
+- p = (int *)shm_malloc(2*sizeof(int));
+- if(!p){
++ p = (int *)shm_malloc(2 * sizeof(int));
++ if(!p) {
+ LM_ERR("out of shm memory\n");
+ return -1;
+ }
+ dp_crt_idx = p;
+- dp_next_idx = p+1;
++ dp_next_idx = p + 1;
+ *dp_crt_idx = *dp_next_idx = 0;
+
+ LM_DBG("trying to initialize data from db\n");
+@@ -224,7 +227,7 @@ int init_data(void)
+
+ void destroy_data(void)
+ {
+- if(dp_rules_hash){
++ if(dp_rules_hash) {
+ destroy_hash(0);
+ destroy_hash(1);
+ shm_free(dp_rules_hash);
+@@ -240,45 +243,46 @@ void destroy_data(void)
+ int dp_load_db(void)
+ {
+ int i, nr_rows;
+- db1_res_t * res = 0;
+- db_val_t * values;
+- db_row_t * rows;
+- db_key_t query_cols[DP_TABLE_COL_NO] = {
+- &dpid_column, &pr_column,
+- &match_op_column, &match_exp_column, &match_len_column,
+- &subst_exp_column, &repl_exp_column, &attrs_column };
++ db1_res_t *res = 0;
++ db_val_t *values;
++ db_row_t *rows;
++ db_key_t query_cols[DP_TABLE_COL_NO] = {&dpid_column, &pr_column,
++ &match_op_column, &match_exp_column, &match_len_column,
++ &subst_exp_column, &repl_exp_column, &attrs_column};
+
+ db_key_t order = &pr_column;
+
+ dpl_node_t *rule;
+
+ LM_DBG("init\n");
+- if( (*dp_crt_idx) != (*dp_next_idx)){
++ if((*dp_crt_idx) != (*dp_next_idx)) {
+ LM_WARN("a load command already generated, aborting reload...\n");
+ return 0;
+ }
+
+- if (dp_dbf.use_table(dp_db_handle, &dp_table_name) < 0){
++ if(dp_dbf.use_table(dp_db_handle, &dp_table_name) < 0) {
+ LM_ERR("error in use_table %.*s\n", dp_table_name.len, dp_table_name.s);
+ return -1;
+ }
+
+- if (DB_CAPABILITY(dp_dbf, DB_CAP_FETCH)) {
+- if(dp_dbf.query(dp_db_handle,0,0,0,query_cols, 0,
+- DP_TABLE_COL_NO, order, 0) < 0){
++ if(DB_CAPABILITY(dp_dbf, DB_CAP_FETCH)) {
++ if(dp_dbf.query(dp_db_handle, 0, 0, 0, query_cols, 0, DP_TABLE_COL_NO,
++ order, 0)
++ < 0) {
+ LM_ERR("failed to query database!\n");
+ return -1;
+ }
+- if(dp_dbf.fetch_result(dp_db_handle, &res, dp_fetch_rows)<0) {
++ if(dp_dbf.fetch_result(dp_db_handle, &res, dp_fetch_rows) < 0) {
+ LM_ERR("failed to fetch\n");
+- if (res)
++ if(res)
+ dp_dbf.free_result(dp_db_handle, res);
+ return -1;
+ }
+ } else {
+ /*select the whole table and all the columns*/
+- if(dp_dbf.query(dp_db_handle,0,0,0,query_cols, 0,
+- DP_TABLE_COL_NO, order, &res) < 0){
++ if(dp_dbf.query(dp_db_handle, 0, 0, 0, query_cols, 0, DP_TABLE_COL_NO,
++ order, &res)
++ < 0) {
+ LM_ERR("failed to query database\n");
+ return -1;
+ }
+@@ -286,38 +290,37 @@ int dp_load_db(void)
+
+ nr_rows = RES_ROW_N(res);
+
+- *dp_next_idx = ((*dp_crt_idx) == 0)? 1:0;
++ *dp_next_idx = ((*dp_crt_idx) == 0) ? 1 : 0;
+ destroy_hash(*dp_next_idx);
+
+- if(nr_rows == 0){
++ if(nr_rows == 0) {
+ LM_WARN("no data in the db\n");
+ goto end;
+ }
+
+ do {
+- for(i=0; i<RES_ROW_N(res); i++){
+- rows = RES_ROWS(res);
++ for(i = 0; i < RES_ROW_N(res); i++) {
++ rows = RES_ROWS(res);
+
+- values = ROW_VALUES(rows+i);
++ values = ROW_VALUES(rows + i);
+
+- if((rule = build_rule(values)) ==0 )
++ if((rule = build_rule(values)) == 0)
+ goto err2;
+
+ if(add_rule2hash(rule, *dp_next_idx) != 0)
+ goto err2;
+-
+ }
+- if (DB_CAPABILITY(dp_dbf, DB_CAP_FETCH)) {
+- if(dp_dbf.fetch_result(dp_db_handle, &res, dp_fetch_rows)<0) {
++ if(DB_CAPABILITY(dp_dbf, DB_CAP_FETCH)) {
++ if(dp_dbf.fetch_result(dp_db_handle, &res, dp_fetch_rows) < 0) {
+ LM_ERR("failure while fetching!\n");
+- if (res)
++ if(res)
+ dp_dbf.free_result(dp_db_handle, res);
+ return -1;
+ }
+ } else {
+ break;
+ }
+- } while(RES_ROW_N(res)>0);
++ } while(RES_ROW_N(res) > 0);
+
+
+ end:
+@@ -328,7 +331,8 @@ end:
+ return 0;
+
+ err2:
+- if(rule) destroy_rule(rule);
++ if(rule)
++ destroy_rule(rule);
+ destroy_hash(*dp_next_idx);
+ dp_dbf.free_result(dp_db_handle, res);
+ *dp_next_idx = *dp_crt_idx;
+@@ -340,16 +344,17 @@ int dpl_str_to_shm(str src, str *dest, i
+ {
+ int mdup = 0;
+
+- if(src.len ==0 || src.s ==0)
++ if(src.len == 0 || src.s == 0)
+ return 0;
+
+- if(mterm!=0 && PV_MARKER=='$') {
+- if(src.len>1 && src.s[src.len-1]=='$' && src.s[src.len-2]!='$') {
++ if(mterm != 0 && PV_MARKER == '$') {
++ if(src.len > 1 && src.s[src.len - 1] == '$'
++ && src.s[src.len - 2] != '$') {
+ mdup = 1;
+ }
+ }
+- dest->s = (char*)shm_malloc((src.len+1+mdup) * sizeof(char));
+- if(!dest->s){
++ dest->s = (char *)shm_malloc((src.len + 1 + mdup) * sizeof(char));
++ if(!dest->s) {
+ LM_ERR("out of shm memory\n");
+ return -1;
+ }
+@@ -378,28 +383,28 @@ pcre *reg_ex_comp(const char *pattern, i
+ size_t size;
+
+ re = pcre_compile(pattern, 0, &error, &err_offset, NULL);
+- if (re == NULL) {
+- LM_ERR("PCRE compilation of '%s' failed at offset %d: %s\n",
+- pattern, err_offset, error);
++ if(re == NULL) {
++ LM_ERR("PCRE compilation of '%s' failed at offset %d: %s\n", pattern,
++ err_offset, error);
+ return (pcre *)0;
+ }
+ rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size);
+- if (rc != 0) {
++ if(rc != 0) {
+ pcre_free(re);
+ LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n",
+ pattern, rc);
+ return (pcre *)0;
+ }
+ rc = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, cap_cnt);
+- if (rc != 0) {
++ if(rc != 0) {
+ pcre_free(re);
+ LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n",
+ pattern, rc);
+ return (pcre *)0;
+ }
+- if(mtype==0) {
++ if(mtype == 0) {
+ result = (pcre *)shm_malloc(size);
+- if (result == NULL) {
++ if(result == NULL) {
+ pcre_free(re);
+ LM_ERR("not enough shared memory for compiled PCRE pattern\n");
+ return (pcre *)0;
+@@ -414,20 +419,20 @@ pcre *reg_ex_comp(const char *pattern, i
+
+
+ /*compile the expressions, and if ok, build the rule */
+-dpl_node_t * build_rule(db_val_t * values)
++dpl_node_t *build_rule(db_val_t *values)
+ {
+ pcre *match_comp, *subst_comp;
+ struct subst_expr *repl_comp;
+- dpl_node_t * new_rule;
++ dpl_node_t *new_rule;
+ str match_exp, subst_exp, repl_exp, attrs;
+ int matchop;
+- int cap_cnt=0;
+- unsigned int tflags=0;
++ int cap_cnt = 0;
++ unsigned int tflags = 0;
+
+- matchop = VAL_INT(values+2);
++ matchop = VAL_INT(values + 2);
+
+- if((matchop != DP_REGEX_OP) && (matchop!=DP_EQUAL_OP)
+- && (matchop!=DP_FNMATCH_OP)){
++ if((matchop != DP_REGEX_OP) && (matchop != DP_EQUAL_OP)
++ && (matchop != DP_FNMATCH_OP)) {
+ LM_ERR("invalid value for match operator\n");
+ return NULL;
+ }
+@@ -437,15 +442,15 @@ dpl_node_t * build_rule(db_val_t * value
+ new_rule = 0;
+
+ GET_STR_VALUE(match_exp, values, 3);
+- if(matchop == DP_REGEX_OP){
+- if(unlikely(dp_match_dynamic==1)) {
+- if(dpl_check_pv(&match_exp)==0) {
++ if(matchop == DP_REGEX_OP) {
++ if(unlikely(dp_match_dynamic == 1)) {
++ if(dpl_check_pv(&match_exp) == 0) {
+ tflags |= DP_TFLAGS_PV_MATCH;
+ }
+ }
+- if(!(tflags&DP_TFLAGS_PV_MATCH)) {
++ if(!(tflags & DP_TFLAGS_PV_MATCH)) {
+ match_comp = reg_ex_comp(match_exp.s, &cap_cnt, 0);
+- if(!match_comp){
++ if(!match_comp) {
+ LM_ERR("failed to compile match expression %.*s\n",
+ match_exp.len, match_exp.s);
+ goto err;
+@@ -454,9 +459,9 @@ dpl_node_t * build_rule(db_val_t * value
+ }
+
+ GET_STR_VALUE(repl_exp, values, 6);
+- if(repl_exp.len && repl_exp.s){
++ if(repl_exp.len && repl_exp.s) {
+ repl_comp = repl_exp_parse(repl_exp);
+- if(!repl_comp){
++ if(!repl_comp) {
+ LM_ERR("failed to compile replacing expression %.*s\n",
+ repl_exp.len, repl_exp.s);
+ goto err;
+@@ -465,20 +470,20 @@ dpl_node_t * build_rule(db_val_t * value
+
+ cap_cnt = 0;
+ GET_STR_VALUE(subst_exp, values, 5);
+- if(subst_exp.s && subst_exp.len){
+- if(unlikely(dp_match_dynamic==1)) {
+- if(dpl_check_pv(&subst_exp)==0) {
++ if(subst_exp.s && subst_exp.len) {
++ if(unlikely(dp_match_dynamic == 1)) {
++ if(dpl_check_pv(&subst_exp) == 0) {
+ tflags |= DP_TFLAGS_PV_SUBST;
+ }
+ }
+- if(!(tflags&DP_TFLAGS_PV_SUBST)) {
++ if(!(tflags & DP_TFLAGS_PV_SUBST)) {
+ subst_comp = reg_ex_comp(subst_exp.s, &cap_cnt, 0);
+- if(!subst_comp){
++ if(!subst_comp) {
+ LM_ERR("failed to compile subst expression %.*s\n",
+ subst_exp.len, subst_exp.s);
+ goto err;
+ }
+- if (cap_cnt > MAX_REPLACE_WITH) {
++ if(cap_cnt > MAX_REPLACE_WITH) {
+ LM_ERR("subst expression %.*s has too many sub-expressions\n",
+ subst_exp.len, subst_exp.s);
+ goto err;
+@@ -486,72 +491,77 @@ dpl_node_t * build_rule(db_val_t * value
+ }
+ }
+
+- LM_DBG("building rule for [%d:%.*s/%.*s/%.*s]\n", matchop,
+- match_exp.len, ZSW(match_exp.s), subst_exp.len, ZSW(subst_exp.s),
+- repl_exp.len, ZSW(repl_exp.s));
+- if (!(tflags&(DP_TFLAGS_PV_SUBST|DP_TFLAGS_PV_MATCH)) &&
+- repl_comp && (cap_cnt < repl_comp->max_pmatch) &&
+- (repl_comp->max_pmatch != 0))
+- {
++ LM_DBG("building rule for [%d:%.*s/%.*s/%.*s]\n", matchop, match_exp.len,
++ ZSW(match_exp.s), subst_exp.len, ZSW(subst_exp.s), repl_exp.len,
++ ZSW(repl_exp.s));
++ if(!(tflags & (DP_TFLAGS_PV_SUBST | DP_TFLAGS_PV_MATCH)) && repl_comp
++ && (cap_cnt < repl_comp->max_pmatch)
++ && (repl_comp->max_pmatch != 0)) {
+ LM_ERR("repl_exp %.*s refers to %d sub-expressions, but "
+- "subst_exp %.*s has only %d\n",
+- repl_exp.len, repl_exp.s, repl_comp->max_pmatch,
+- subst_exp.len, subst_exp.s, cap_cnt);
++ "subst_exp %.*s has only %d\n",
++ repl_exp.len, repl_exp.s, repl_comp->max_pmatch, subst_exp.len,
++ subst_exp.s, cap_cnt);
+ goto err;
+ }
+
+ new_rule = (dpl_node_t *)shm_malloc(sizeof(dpl_node_t));
+- if(!new_rule){
++ if(!new_rule) {
+ LM_ERR("out of shm memory(new_rule)\n");
+ goto err;
+ }
+ memset(new_rule, 0, sizeof(dpl_node_t));
+
+- if(dpl_str_to_shm(match_exp, &new_rule->match_exp,
+- tflags&DP_TFLAGS_PV_MATCH)!=0)
++ if(dpl_str_to_shm(
++ match_exp, &new_rule->match_exp, tflags & DP_TFLAGS_PV_MATCH)
++ != 0)
+ goto err;
+
+- if(dpl_str_to_shm(subst_exp, &new_rule->subst_exp,
+- tflags&DP_TFLAGS_PV_SUBST)!=0)
++ if(dpl_str_to_shm(
++ subst_exp, &new_rule->subst_exp, tflags & DP_TFLAGS_PV_SUBST)
++ != 0)
+ goto err;
+
+- if(dpl_str_to_shm(repl_exp, &new_rule->repl_exp, 0)!=0)
++ if(dpl_str_to_shm(repl_exp, &new_rule->repl_exp, 0) != 0)
+ goto err;
+
+ /*set the rest of the rule fields*/
+- new_rule->dpid = VAL_INT(values);
+- new_rule->pr = VAL_INT(values+1);
+- new_rule->matchlen = VAL_INT(values+4);
+- new_rule->matchop = matchop;
++ new_rule->dpid = VAL_INT(values);
++ new_rule->pr = VAL_INT(values + 1);
++ new_rule->matchlen = VAL_INT(values + 4);
++ new_rule->matchop = matchop;
+ GET_STR_VALUE(attrs, values, 7);
+- if(dpl_str_to_shm(attrs, &new_rule->attrs, 0)!=0)
++ if(dpl_str_to_shm(attrs, &new_rule->attrs, 0) != 0)
+ goto err;
+
+ LM_DBG("attrs are: '%.*s'\n", new_rule->attrs.len, new_rule->attrs.s);
+
+ new_rule->match_comp = match_comp;
+ new_rule->subst_comp = subst_comp;
+- new_rule->repl_comp = repl_comp;
+- new_rule->tflags = tflags;
++ new_rule->repl_comp = repl_comp;
++ new_rule->tflags = tflags;
+
+ return new_rule;
+
+ err:
+- if(match_comp) shm_free(match_comp);
+- if(subst_comp) shm_free(subst_comp);
+- if(repl_comp) repl_expr_free(repl_comp);
+- if(new_rule) destroy_rule(new_rule);
++ if(match_comp)
++ shm_free(match_comp);
++ if(subst_comp)
++ shm_free(subst_comp);
++ if(repl_comp)
++ repl_expr_free(repl_comp);
++ if(new_rule)
++ destroy_rule(new_rule);
+ return NULL;
+ }
+
+
+-int add_rule2hash(dpl_node_t * rule, int h_index)
++int add_rule2hash(dpl_node_t *rule, int h_index)
+ {
+ dpl_id_p crt_idp, last_idp;
+ dpl_index_p indexp, last_indexp, new_indexp;
+ int new_id;
+
+- if(!dp_rules_hash){
++ if(!dp_rules_hash) {
+ LM_ERR("data not allocated\n");
+ return -1;
+ }
+@@ -559,15 +569,15 @@ int add_rule2hash(dpl_node_t * rule, int
+ new_id = 0;
+
+ /*search for the corresponding dpl_id*/
+- for(crt_idp = last_idp =dp_rules_hash[h_index]; crt_idp!= NULL;
++ for(crt_idp = last_idp = dp_rules_hash[h_index]; crt_idp != NULL;
+ last_idp = crt_idp, crt_idp = crt_idp->next)
+ if(crt_idp->dp_id == rule->dpid)
+ break;
+
+ /*didn't find a dpl_id*/
+- if(!crt_idp){
+- crt_idp = (dpl_id_t*)shm_malloc(sizeof(dpl_id_t));
+- if(!crt_idp){
++ if(!crt_idp) {
++ crt_idp = (dpl_id_t *)shm_malloc(sizeof(dpl_id_t));
++ if(!crt_idp) {
+ LM_ERR("out of shm memory (crt_idp)\n");
+ return -1;
+ }
+@@ -578,11 +588,12 @@ int add_rule2hash(dpl_node_t * rule, int
+ }
+
+ /*search for the corresponding dpl_index*/
+- for(indexp = last_indexp =crt_idp->first_index; indexp!=NULL;
+- last_indexp = indexp, indexp = indexp->next){
++ for(indexp = last_indexp = crt_idp->first_index; indexp != NULL;
++ last_indexp = indexp, indexp = indexp->next) {
+ if(indexp->len == rule->matchlen)
+ goto add_rule;
+- if((rule->matchlen!=0)&&((indexp->len)?(indexp->len>rule->matchlen):1))
++ if((rule->matchlen != 0)
++ && ((indexp->len) ? (indexp->len > rule->matchlen) : 1))
+ goto add_index;
+ }
+
+@@ -590,18 +601,18 @@ add_index:
+ LM_DBG("new index , len %i\n", rule->matchlen);
+
+ new_indexp = (dpl_index_t *)shm_malloc(sizeof(dpl_index_t));
+- if(!new_indexp){
++ if(!new_indexp) {
+ LM_ERR("out of shm memory\n");
+ goto err;
+ }
+- memset(new_indexp , 0, sizeof(dpl_index_t));
++ memset(new_indexp, 0, sizeof(dpl_index_t));
+ new_indexp->next = indexp;
+ new_indexp->len = rule->matchlen;
+
+ /*add as first index*/
+- if(last_indexp == indexp){
++ if(last_indexp == indexp) {
+ crt_idp->first_index = new_indexp;
+- }else{
++ } else {
+ last_indexp->next = new_indexp;
+ }
+
+@@ -617,13 +628,13 @@ add_rule:
+
+ indexp->last_rule = rule;
+
+- if(new_id){
++ if(new_id) {
+ crt_idp->next = dp_rules_hash[h_index];
+ dp_rules_hash[h_index] = crt_idp;
+ }
+ LM_DBG("added the rule id %i index %i pr %i next %p to the "
+- "index with %i len\n", rule->dpid, rule->matchlen,
+- rule->pr, rule->next, indexp->len);
++ "index with %i len\n",
++ rule->dpid, rule->matchlen, rule->pr, rule->next, indexp->len);
+
+ return 0;
+
+@@ -643,24 +654,23 @@ void destroy_hash(int index)
+ if(!dp_rules_hash[index])
+ return;
+
+- for(crt_idp = dp_rules_hash[index]; crt_idp != NULL;){
++ for(crt_idp = dp_rules_hash[index]; crt_idp != NULL;) {
+
+- for(indexp = crt_idp->first_index; indexp != NULL;){
++ for(indexp = crt_idp->first_index; indexp != NULL;) {
+
+- for(rulep = indexp->first_rule; rulep!= NULL;){
++ for(rulep = indexp->first_rule; rulep != NULL;) {
+
+ destroy_rule(rulep);
+
+ indexp->first_rule = rulep->next;
+ shm_free(rulep);
+- rulep=0;
+- rulep= indexp->first_rule;
++ rulep = 0;
++ rulep = indexp->first_rule;
+ }
+- crt_idp->first_index= indexp->next;
++ crt_idp->first_index = indexp->next;
+ shm_free(indexp);
+- indexp=0;
++ indexp = 0;
+ indexp = crt_idp->first_index;
+-
+ }
+
+ dp_rules_hash[index] = crt_idp->next;
+@@ -673,13 +683,13 @@ void destroy_hash(int index)
+ }
+
+
+-void destroy_rule(dpl_node_t * rule){
++void destroy_rule(dpl_node_t *rule)
++{
+
+ if(!rule)
+ return;
+
+- LM_DBG("destroying rule with priority %i\n",
+- rule->pr);
++ LM_DBG("destroying rule with priority %i\n", rule->pr);
+
+ if(rule->match_comp)
+ shm_free(rule->match_comp);
+@@ -712,7 +722,7 @@ dpl_id_p select_dpid(int id)
+ if(!dp_rules_hash || !dp_crt_idx)
+ return NULL;
+
+- for(idp = dp_rules_hash[*dp_crt_idx]; idp!=NULL; idp = idp->next)
++ for(idp = dp_rules_hash[*dp_crt_idx]; idp != NULL; idp = idp->next)
+ if(idp->dp_id == id)
+ return idp;
+
+@@ -731,11 +741,14 @@ void list_hash(int h_index)
+ if(!dp_rules_hash[h_index])
+ return;
+
+- for(crt_idp=dp_rules_hash[h_index]; crt_idp!=NULL; crt_idp = crt_idp->next){
++ for(crt_idp = dp_rules_hash[h_index]; crt_idp != NULL;
++ crt_idp = crt_idp->next) {
+ LM_DBG("DPID: %i, pointer %p\n", crt_idp->dp_id, crt_idp);
+- for(indexp=crt_idp->first_index; indexp!=NULL;indexp= indexp->next){
++ for(indexp = crt_idp->first_index; indexp != NULL;
++ indexp = indexp->next) {
+ LM_DBG("INDEX LEN: %i\n", indexp->len);
+- for(rulep = indexp->first_rule; rulep!= NULL;rulep = rulep->next){
++ for(rulep = indexp->first_rule; rulep != NULL;
++ rulep = rulep->next) {
+ list_rule(rulep);
+ }
+ }
+@@ -746,12 +759,9 @@ void list_hash(int h_index)
+ void list_rule(dpl_node_t *rule)
+ {
+ LM_DBG("RULE %p: pr %i next %p op %d tflags %u match_exp %.*s, "
+- "subst_exp %.*s, repl_exp %.*s and attrs %.*s\n", rule,
+- rule->pr, rule->next,
+- rule->matchop, rule->tflags,
+- rule->match_exp.len, ZSW(rule->match_exp.s),
+- rule->subst_exp.len, ZSW(rule->subst_exp.s),
+- rule->repl_exp.len, ZSW(rule->repl_exp.s),
+- rule->attrs.len, ZSW(rule->attrs.s));
+-
++ "subst_exp %.*s, repl_exp %.*s and attrs %.*s\n",
++ rule, rule->pr, rule->next, rule->matchop, rule->tflags,
++ rule->match_exp.len, ZSW(rule->match_exp.s), rule->subst_exp.len,
++ ZSW(rule->subst_exp.s), rule->repl_exp.len, ZSW(rule->repl_exp.s),
++ rule->attrs.len, ZSW(rule->attrs.s));
+ }
+--- a/src/modules/dialplan/dp_db.h
++++ b/src/modules/dialplan/dp_db.h
+@@ -32,30 +32,30 @@
+ #include "../../core/str.h"
+ #include "../../lib/srdb1/db.h"
+
+-#define DP_TABLE_NAME "dialplan"
+-#define DPID_COL "dpid"
+-#define PR_COL "pr"
+-#define MATCH_OP_COL "match_op"
+-#define MATCH_EXP_COL "match_exp"
+-#define MATCH_LEN_COL "match_len"
+-#define SUBST_EXP_COL "subst_exp"
+-#define REPL_EXP_COL "repl_exp"
+-#define ATTRS_COL "attrs"
++#define DP_TABLE_NAME "dialplan"
++#define DPID_COL "dpid"
++#define PR_COL "pr"
++#define MATCH_OP_COL "match_op"
++#define MATCH_EXP_COL "match_exp"
++#define MATCH_LEN_COL "match_len"
++#define SUBST_EXP_COL "subst_exp"
++#define REPL_EXP_COL "repl_exp"
++#define ATTRS_COL "attrs"
+
+
+-#define DP_TABLE_VERSION 2
+-#define DP_TABLE_COL_NO 8
++#define DP_TABLE_VERSION 2
++#define DP_TABLE_COL_NO 8
+
+ extern str dp_db_url;
+ extern str dp_table_name;
+-extern str dpid_column;
+-extern str pr_column;
+-extern str match_op_column;
+-extern str match_exp_column;
+-extern str match_len_column;
+-extern str subst_exp_column;
+-extern str repl_exp_column;
+-extern str attrs_column;
++extern str dpid_column;
++extern str pr_column;
++extern str match_op_column;
++extern str match_exp_column;
++extern str match_len_column;
++extern str subst_exp_column;
++extern str repl_exp_column;
++extern str attrs_column;
+
+ int init_db_data();
+ int dp_connect_db();
+--- a/src/modules/dialplan/dp_repl.c
++++ b/src/modules/dialplan/dp_repl.c
+@@ -42,27 +42,28 @@ typedef struct dpl_dyn_pcre
+ int cnt;
+ str expr;
+
+- struct dpl_dyn_pcre * next; /* next rule */
++ struct dpl_dyn_pcre *next; /* next rule */
+ } dpl_dyn_pcre_t, *dpl_dyn_pcre_p;
+
+-static void dpl_get_avp_val(avp_t *avp, str *dst) {
++static void dpl_get_avp_val(avp_t *avp, str *dst)
++{
+ avp_value_t val;
+
+- if (avp==0 || dst==0) return;
++ if(avp == 0 || dst == 0)
++ return;
+
+ /* Warning! it uses static buffer from int2str !!! */
+
+ get_avp_val(avp, &val);
+- if (avp->flags & AVP_VAL_STR) {
++ if(avp->flags & AVP_VAL_STR) {
+ *dst = val.s;
+- }
+- else { /* probably (!) number */
++ } else { /* probably (!) number */
+ dst->s = int2str(val.n, &dst->len);
+ }
+ }
+
+ int dpl_dyn_printf_s(sip_msg_t *msg, const pv_elem_p elem,
+- const pv_elem_p avp_elem, str *val, pv_elem_p *elem_prev, str *vexpr)
++ const pv_elem_p avp_elem, str *val, pv_elem_p *elem_prev, str *vexpr)
+ {
+ pv_elem_p e = NULL;
+ pv_elem_p t = NULL;
+@@ -70,45 +71,52 @@ int dpl_dyn_printf_s(sip_msg_t *msg, con
+ str v = STR_NULL;
+ int ret = -1;
+
+- if(elem==NULL||avp_elem==NULL||elem_prev==NULL||vexpr==NULL) return -1;
+- if(str_append(&(avp_elem->text), val, &s)<0) return -1;
++ if(elem == NULL || avp_elem == NULL || elem_prev == NULL || vexpr == NULL)
++ return -1;
++ if(str_append(&(avp_elem->text), val, &s) < 0)
++ return -1;
+
+- if(pv_parse_format(&s, &e)<0) {
++ if(pv_parse_format(&s, &e) < 0) {
+ LM_ERR("parsing expression: %.*s\n", s.len, s.s);
+ goto clean;
+ }
+- if(*elem_prev==NULL && elem!=avp_elem) {
++ if(*elem_prev == NULL && elem != avp_elem) {
+ LM_DBG("search for elem_prev\n");
+- for(t=elem; t!=NULL; t=t->next) {
+- if(t->next==avp_elem) { *elem_prev = t;
++ for(t = elem; t != NULL; t = t->next) {
++ if(t->next == avp_elem) {
++ *elem_prev = t;
+ LM_DBG("found!\n");
+ }
+ }
+ }
+- if(*elem_prev) (*elem_prev)->next = e;
++ if(*elem_prev)
++ (*elem_prev)->next = e;
+ e->next = avp_elem->next;
+- if(pv_printf_s(msg, e, &v)<0){
++ if(pv_printf_s(msg, e, &v) < 0) {
+ LM_ERR("cannot get avp pcre dynamic expression value\n");
+ goto clean;
+ }
+ /* pv_printf_s uses pv_get_buffer() we do need to copy */
+ vexpr->len = v.len;
+- vexpr->s = pkg_malloc(sizeof(char)*(v.len+1));
+- if(vexpr->s==NULL) {
++ vexpr->s = pkg_malloc(sizeof(char) * (v.len + 1));
++ if(vexpr->s == NULL) {
+ PKG_MEM_ERROR;
+ goto clean;
+ }
+ strcpy(vexpr->s, v.s);
+ ret = 0;
+ clean:
+- if(s.s) pkg_free(s.s);
+- if(e) pkg_free(e);
+- if(*elem_prev) (*elem_prev)->next = avp_elem;
++ if(s.s)
++ pkg_free(s.s);
++ if(e)
++ pkg_free(e);
++ if(*elem_prev)
++ (*elem_prev)->next = avp_elem;
+ return ret;
+ }
+
+ int dpl_get_avp_values(sip_msg_t *msg, const pv_elem_p elem,
+- const pv_elem_p avp_elem, struct str_list **out)
++ const pv_elem_p avp_elem, struct str_list **out)
+ {
+ struct usr_avp *avp = NULL;
+ unsigned short name_type;
+@@ -120,16 +128,17 @@ int dpl_get_avp_values(sip_msg_t *msg, c
+ pv_elem_p elem_prev = NULL;
+ struct str_list *tl = NULL;
+
+- if(elem==NULL||avp_elem==NULL||out==NULL||*out==NULL) {
++ if(elem == NULL || avp_elem == NULL || out == NULL || *out == NULL) {
+ LM_ERR("wrong parameters\n");
+ return -1;
+ }
+- if(pv_get_avp_name(msg, &(avp_elem->spec->pvp), &avp_name, &name_type)!=0) {
++ if(pv_get_avp_name(msg, &(avp_elem->spec->pvp), &avp_name, &name_type)
++ != 0) {
+ LM_ERR("invalid avp name\n");
+ return -1;
+ }
+ avp = search_first_avp(name_type, avp_name, &avp_value, &state);
+- if(avp==NULL) {
++ if(avp == NULL) {
+ LM_ERR("can't find first avp\n");
+ return -1;
+ }
+@@ -139,10 +148,10 @@ int dpl_get_avp_values(sip_msg_t *msg, c
+ /*LM_DBG("elem[%p] avp_elem[%p], elem_prev[%p] [%.*s]\n",
+ elem, avp_elem, elem_prev, tl->s.len, tl->s.s);*/
+ sum = tl->s.len;
+- while ((avp=search_next_avp(&state, &avp_value))!=0) {
++ while((avp = search_next_avp(&state, &avp_value)) != 0) {
+ dpl_get_avp_val(avp, &s);
+ dpl_dyn_printf_s(msg, elem, avp_elem, &s, &elem_prev, &ts);
+- if(append_str_list(ts.s, ts.len, &tl, &sum)==NULL) {
++ if(append_str_list(ts.s, ts.len, &tl, &sum) == NULL) {
+ while(*out) {
+ tl = (*out)->next;
+ pkg_free(*out);
+@@ -160,18 +169,20 @@ int dpl_get_avp_values(sip_msg_t *msg, c
+ int dpl_detect_avp_indx(const pv_elem_p elem, pv_elem_p *avp)
+ {
+ int num, num_avp_all;
+- pv_elem_p e = elem;;
+- if(elem==NULL||avp==NULL) return -1;
++ pv_elem_p e = elem;
++ ;
++ if(elem == NULL || avp == NULL)
++ return -1;
+
+- for(e=elem, num=num_avp_all=0; e!=NULL; e=e->next, num++) {
+- if(e->spec!=NULL && e->spec->type==PVT_AVP &&
+- e->spec->pvp.pvi.type==PV_IDX_ITR)
+- {
++ for(e = elem, num = num_avp_all = 0; e != NULL; e = e->next, num++) {
++ if(e->spec != NULL && e->spec->type == PVT_AVP
++ && e->spec->pvp.pvi.type == PV_IDX_ITR) {
+ *avp = e;
+ num_avp_all++;
+ }
+ }
+- if(num_avp_all==1) return 1; /* just one avp_indx supported */
++ if(num_avp_all == 1)
++ return 1; /* just one avp_indx supported */
+ return 0;
+ }
+
+@@ -180,29 +191,29 @@ pcre *dpl_dyn_pcre_comp(sip_msg_t *msg,
+ pcre *re = NULL;
+ int ccnt = 0;
+
+- if(expr==NULL || expr->s==NULL || expr->len<=0 ||
+- vexpr==NULL || vexpr->s==NULL || vexpr->len<=0)
++ if(expr == NULL || expr->s == NULL || expr->len <= 0 || vexpr == NULL
++ || vexpr->s == NULL || vexpr->len <= 0)
+ return NULL;
+
+ re = reg_ex_comp(vexpr->s, &ccnt, 1);
+ if(!re) {
+- if(expr!=vexpr)
++ if(expr != vexpr)
+ LM_ERR("failed to compile pcre expression: %.*s (%.*s)\n",
+- expr->len, expr->s, vexpr->len, vexpr->s);
++ expr->len, expr->s, vexpr->len, vexpr->s);
+ else
+- LM_ERR("failed to compile pcre expression: %.*s\n",
+- vexpr->len, vexpr->s);
++ LM_ERR("failed to compile pcre expression: %.*s\n", vexpr->len,
++ vexpr->s);
+ return NULL;
+ }
+ if(cap_cnt) {
+ *cap_cnt = ccnt;
+ }
+- if(expr!=vexpr)
+- LM_DBG("compiled dynamic pcre expression: %.*s (%.*s) %d\n",
+- expr->len, expr->s, vexpr->len, vexpr->s, ccnt);
++ if(expr != vexpr)
++ LM_DBG("compiled dynamic pcre expression: %.*s (%.*s) %d\n", expr->len,
++ expr->s, vexpr->len, vexpr->s, ccnt);
+ else
+- LM_DBG("compiled dynamic pcre expression: %.*s %d\n",
+- vexpr->len, vexpr->s, ccnt);
++ LM_DBG("compiled dynamic pcre expression: %.*s %d\n", vexpr->len,
++ vexpr->s, ccnt);
+ return re;
+ }
+
+@@ -218,35 +229,33 @@ dpl_dyn_pcre_p dpl_dynamic_pcre_list(sip
+ int cnt = 0;
+ str vexpr = STR_NULL;
+
+- if(expr==NULL || expr->s==NULL || expr->len<=0)
+- {
++ if(expr == NULL || expr->s == NULL || expr->len <= 0) {
+ LM_ERR("wrong parameters\n");
+ return NULL;
+ }
+
+- if(pv_parse_format(expr, &elem)<0) {
+- LM_ERR("parsing pcre expression: %.*s\n",
+- expr->len, expr->s);
++ if(pv_parse_format(expr, &elem) < 0) {
++ LM_ERR("parsing pcre expression: %.*s\n", expr->len, expr->s);
+ return NULL;
+ }
+ LM_DBG("parsed pcre expression: %.*s\n", expr->len, expr->s);
+ if(dpl_detect_avp_indx(elem, &avp_elem)) {
+ l = pkg_malloc(sizeof(struct str_list));
+- if(l==NULL) {
++ if(l == NULL) {
+ PKG_MEM_ERROR;
+ goto error;
+ }
+ memset(l, 0, sizeof(struct str_list));
+- if(dpl_get_avp_values(msg, elem, avp_elem, &l)<0) {
++ if(dpl_get_avp_values(msg, elem, avp_elem, &l) < 0) {
+ LM_ERR("can't get list of avp values\n");
+ goto error;
+ }
+ t = l;
+ while(t) {
+ re = dpl_dyn_pcre_comp(msg, &(t->s), &(t->s), &cnt);
+- if(re!=NULL) {
++ if(re != NULL) {
+ rt = pkg_malloc(sizeof(dpl_dyn_pcre_t));
+- if(rt==NULL) {
++ if(rt == NULL) {
+ PKG_MEM_ERROR;
+ goto error;
+ }
+@@ -259,17 +268,16 @@ dpl_dyn_pcre_p dpl_dynamic_pcre_list(sip
+ }
+ t = t->next;
+ }
+- }
+- else {
+- if(pv_printf_s(msg, elem, &vexpr)<0){
++ } else {
++ if(pv_printf_s(msg, elem, &vexpr) < 0) {
+ LM_ERR("cannot get pcre dynamic expression value: %.*s\n",
+ expr->len, expr->s);
+ goto error;
+ }
+ re = dpl_dyn_pcre_comp(msg, expr, &vexpr, &cnt);
+- if(re!=NULL) {
++ if(re != NULL) {
+ rt = pkg_malloc(sizeof(dpl_dyn_pcre_t));
+- if(rt==NULL) {
++ if(rt == NULL) {
+ PKG_MEM_ERROR;
+ goto error;
+ }
+@@ -285,15 +293,18 @@ dpl_dyn_pcre_p dpl_dynamic_pcre_list(sip
+ error:
+ while(re_list) {
+ rt = re_list->next;
+- if(re_list->re) pcre_free(re_list->re);
++ if(re_list->re)
++ pcre_free(re_list->re);
+ pkg_free(re_list);
+ re_list = rt;
+ }
+ clean:
+- if(elem) pv_elem_free_all(elem);
++ if(elem)
++ pv_elem_free_all(elem);
+ while(l) {
+ t = l->next;
+- if(l->s.s) pkg_free(l->s.s);
++ if(l->s.s)
++ pkg_free(l->s.s);
+ pkg_free(l);
+ l = t;
+ }
+@@ -305,7 +316,7 @@ void repl_expr_free(struct subst_expr *s
+ if(!se)
+ return;
+
+- if(se->replacement.s){
++ if(se->replacement.s) {
+ shm_free(se->replacement.s);
+ se->replacement.s = 0;
+ }
+@@ -315,13 +326,13 @@ void repl_expr_free(struct subst_expr *s
+ }
+
+
+-struct subst_expr* repl_exp_parse(str subst)
++struct subst_expr *repl_exp_parse(str subst)
+ {
+ struct replace_with rw[MAX_REPLACE_WITH];
+ int rw_no;
+- struct subst_expr * se;
++ struct subst_expr *se;
+ int replace_all;
+- char * p, *end, *repl, *repl_end;
++ char *p, *end, *repl, *repl_end;
+ int max_pmatch, r;
+ str shms;
+
+@@ -329,7 +340,7 @@ struct subst_expr* repl_exp_parse(str su
+ replace_all = 0;
+ shms.s = NULL;
+
+- if (!(shms.s=shm_malloc((subst.len+1) * sizeof(char))) ){
++ if(!(shms.s = shm_malloc((subst.len + 1) * sizeof(char)))) {
+ LM_ERR("out of shm memory\n");
+ goto error;
+ }
+@@ -342,39 +353,41 @@ struct subst_expr* repl_exp_parse(str su
+ rw_no = 0;
+
+ repl = p;
+- if((rw_no = parse_repl(rw, &p, end, &max_pmatch, WITHOUT_SEP))< 0) {
++ if((rw_no = parse_repl(rw, &p, end, &max_pmatch, WITHOUT_SEP)) < 0) {
+ LM_ERR("parse repl failed\n");
+ goto error;
+ }
+
+- repl_end=p;
++ repl_end = p;
+
+ /* construct the subst_expr structure */
+- se = shm_malloc(sizeof(struct subst_expr)+
+- ((rw_no)?(rw_no-1)*sizeof(struct replace_with):0));
++ se = shm_malloc(
++ sizeof(struct subst_expr)
++ + ((rw_no) ? (rw_no - 1) * sizeof(struct replace_with) : 0));
+ /* 1 replace_with structure is already included in subst_expr */
+- if (se==0){
++ if(se == 0) {
+ LM_ERR("out of shm memory (subst_expr)\n");
+ goto error;
+ }
+- memset((void*)se, 0, sizeof(struct subst_expr));
++ memset((void *)se, 0, sizeof(struct subst_expr));
+
+ se->replacement.s = shms.s;
+ shms.s = NULL;
+- se->replacement.len=repl_end-repl;
+- if(!rw_no){
++ se->replacement.len = repl_end - repl;
++ if(!rw_no) {
+ replace_all = 1;
+ }
+ /* start copying */
+ LM_DBG("replacement expression is [%.*s]\n", se->replacement.len,
+ se->replacement.s);
+- se->re=0;
+- se->replace_all=replace_all;
+- se->n_escapes=rw_no;
+- se->max_pmatch=max_pmatch;
++ se->re = 0;
++ se->replace_all = replace_all;
++ se->n_escapes = rw_no;
++ se->max_pmatch = max_pmatch;
+
+ /*replace_with is a simple structure, no shm alloc needed*/
+- for (r=0; r<rw_no; r++) se->replace[r]=rw[r];
++ for(r = 0; r < rw_no; r++)
++ se->replace[r] = rw[r];
+ return se;
+
+ error:
+@@ -384,17 +397,17 @@ error:
+ }
+
+
+-#define MAX_PHONE_NB_DIGITS 127
+-static char dp_output_buf[MAX_PHONE_NB_DIGITS+1];
++#define MAX_PHONE_NB_DIGITS 127
++static char dp_output_buf[MAX_PHONE_NB_DIGITS + 1];
+ int rule_translate(sip_msg_t *msg, str *instr, dpl_node_t *rule,
+ pcre *subst_comp, str *result)
+ {
+ int repl_nb, offset, match_nb, rc, cap_cnt;
+ struct replace_with token;
+- struct subst_expr * repl_comp;
++ struct subst_expr *repl_comp;
+ str match;
+ pv_value_t sv;
+- str* uri;
++ str *uri;
+ int ovector[3 * (MAX_REPLACE_WITH + 1)];
+ char *p;
+ int size;
+@@ -404,53 +417,50 @@ int rule_translate(sip_msg_t *msg, str *
+ result->len = 0;
+
+ repl_comp = rule->repl_comp;
+- if(!repl_comp){
++ if(!repl_comp) {
+ LM_DBG("null replacement\n");
+ return 0;
+ }
+
+- if(subst_comp){
++ if(subst_comp) {
+ /*just in case something went wrong at load time*/
+- rc = pcre_fullinfo(subst_comp, NULL, PCRE_INFO_CAPTURECOUNT,
+- &cap_cnt);
+- if (rc != 0) {
+- LM_ERR("pcre_fullinfo on compiled pattern yielded error: %d\n",
+- rc);
++ rc = pcre_fullinfo(subst_comp, NULL, PCRE_INFO_CAPTURECOUNT, &cap_cnt);
++ if(rc != 0) {
++ LM_ERR("pcre_fullinfo on compiled pattern yielded error: %d\n", rc);
+ return -1;
+ }
+- if(repl_comp->max_pmatch > cap_cnt){
++ if(repl_comp->max_pmatch > cap_cnt) {
+ LM_ERR("illegal access to %i-th subexpr of subst expr (max %d)\n",
+ repl_comp->max_pmatch, cap_cnt);
+ return -1;
+ }
+- if (rule->tflags&DP_TFLAGS_PV_SUBST && (cap_cnt > MAX_REPLACE_WITH)) {
++ if(rule->tflags & DP_TFLAGS_PV_SUBST && (cap_cnt > MAX_REPLACE_WITH)) {
+ LM_ERR("subst expression %.*s has too many sub-expressions\n",
+- rule->subst_exp.len, rule->subst_exp.s);
++ rule->subst_exp.len, rule->subst_exp.s);
+ return -1;
+ }
+
+ /*search for the pattern from the compiled subst_exp*/
+- if (pcre_exec(subst_comp, NULL, instr->s, instr->len,
+- 0, 0, ovector, 3 * (MAX_REPLACE_WITH + 1)) <= 0) {
++ if(pcre_exec(subst_comp, NULL, instr->s, instr->len, 0, 0, ovector,
++ 3 * (MAX_REPLACE_WITH + 1))
++ <= 0) {
+ LM_DBG("the string %.*s matched "
+- "the match_exp %.*s but not the subst_exp %.*s!\n",
+- instr->len, instr->s,
+- rule->match_exp.len, rule->match_exp.s,
+- rule->subst_exp.len, rule->subst_exp.s);
++ "the match_exp %.*s but not the subst_exp %.*s!\n",
++ instr->len, instr->s, rule->match_exp.len,
++ rule->match_exp.s, rule->subst_exp.len, rule->subst_exp.s);
+ return -1;
+ }
+ }
+
+ /*simply copy from the replacing string*/
+- if(!subst_comp || (repl_comp->n_escapes <=0)){
+- if(!repl_comp->replacement.s || repl_comp->replacement.len == 0){
++ if(!subst_comp || (repl_comp->n_escapes <= 0)) {
++ if(!repl_comp->replacement.s || repl_comp->replacement.len == 0) {
+ LM_ERR("invalid replacing string\n");
+ goto error;
+ }
+ LM_DBG("simply replace the string, subst_comp %p, n_escapes %i\n",
+ subst_comp, repl_comp->n_escapes);
+- memcpy(result->s, repl_comp->replacement.s,
+- repl_comp->replacement.len);
++ memcpy(result->s, repl_comp->replacement.s, repl_comp->replacement.len);
+ result->len = repl_comp->replacement.len;
+ result->s[result->len] = '\0';
+ return 0;
+@@ -458,91 +468,90 @@ int rule_translate(sip_msg_t *msg, str *
+
+ /* offset- offset in the replacement string */
+ result->len = repl_nb = offset = 0;
+- p=repl_comp->replacement.s;
++ p = repl_comp->replacement.s;
+
+- while( repl_nb < repl_comp->n_escapes){
++ while(repl_nb < repl_comp->n_escapes) {
+
+ token = repl_comp->replace[repl_nb];
+
+- if(offset< token.offset){
+- if((repl_comp->replacement.len < offset)||
+- (result->len + token.offset -offset >= MAX_PHONE_NB_DIGITS)){
++ if(offset < token.offset) {
++ if((repl_comp->replacement.len < offset)
++ || (result->len + token.offset - offset
++ >= MAX_PHONE_NB_DIGITS)) {
+ LM_ERR("invalid length\n");
+ goto error;
+ }
+ /*copy from the replacing string*/
+ size = token.offset - offset;
+ memcpy(result->s + result->len, p + offset, size);
+- LM_DBG("copying <%.*s> from replacing string\n",
+- size, p + offset);
++ LM_DBG("copying <%.*s> from replacing string\n", size, p + offset);
+ result->len += size;
+ offset = token.offset;
+ }
+
+ switch(token.type) {
+ case REPLACE_NMATCH:
+- /*copy from the match subexpression*/
++ /*copy from the match subexpression*/
+ match_nb = token.u.nmatch * 2;
+- match.s = instr->s + ovector[match_nb];
++ match.s = instr->s + ovector[match_nb];
+ match.len = ovector[match_nb + 1] - ovector[match_nb];
+- if(result->len + match.len >= MAX_PHONE_NB_DIGITS){
++ if(result->len + match.len >= MAX_PHONE_NB_DIGITS) {
+ LM_ERR("overflow\n");
+ goto error;
+ }
+
+ memcpy(result->s + result->len, match.s, match.len);
+- LM_DBG("copying match <%.*s> token size %d\n",
+- match.len, match.s, token.size);
++ LM_DBG("copying match <%.*s> token size %d\n", match.len,
++ match.s, token.size);
+ result->len += match.len;
+ offset += token.size;
+ break;
+ case REPLACE_CHAR:
+- if(result->len + 1>= MAX_PHONE_NB_DIGITS){
++ if(result->len + 1 >= MAX_PHONE_NB_DIGITS) {
+ LM_ERR("overflow\n");
+ goto error;
+ }
+ *(result->s + result->len) = token.u.c;
+- LM_DBG("copying char <%c> token size %d\n",
+- token.u.c, token.size);
++ LM_DBG("copying char <%c> token size %d\n", token.u.c,
++ token.size);
+ result->len++;
+ offset += token.size;
+ break;
+- case REPLACE_URI:
+- if ( msg== NULL || msg->first_line.type!=SIP_REQUEST){
++ case REPLACE_URI:
++ if(msg == NULL || msg->first_line.type != SIP_REQUEST) {
+ LM_CRIT("uri substitution attempt on no request"
+ " message\n");
+ break; /* ignore, we can continue */
+ }
+- uri= (msg->new_uri.s)?(&msg->new_uri):
+- (&msg->first_line.u.request.uri);
+- if(result->len+uri->len>=MAX_PHONE_NB_DIGITS){
++ uri = (msg->new_uri.s) ? (&msg->new_uri)
++ : (&msg->first_line.u.request.uri);
++ if(result->len + uri->len >= MAX_PHONE_NB_DIGITS) {
+ LM_ERR("overflow\n");
+ goto error;
+ }
+ memcpy(result->s + result->len, uri->s, uri->len);
+- LM_DBG("copying uri <%.*s> token size %d\n",
+- uri->len, uri->s, token.size);
+- result->len+=uri->len;
++ LM_DBG("copying uri <%.*s> token size %d\n", uri->len, uri->s,
++ token.size);
++ result->len += uri->len;
+ offset += token.size;
+ break;
+ case REPLACE_SPEC:
+- if (msg== NULL) {
++ if(msg == NULL) {
+ LM_DBG("replace spec attempted on no message\n");
+ break;
+ }
+- if (pv_get_spec_value(msg, &token.u.spec, &sv) != 0) {
++ if(pv_get_spec_value(msg, &token.u.spec, &sv) != 0) {
+ LM_CRIT("item substitution returned error\n");
+ break; /* ignore, we can continue */
+ }
+- if(result->len+sv.rs.len>=MAX_PHONE_NB_DIGITS){
++ if(result->len + sv.rs.len >= MAX_PHONE_NB_DIGITS) {
+ LM_ERR("rule_translate: overflow\n");
+ goto error;
+ }
+- memcpy(result->s + result->len, sv.rs.s,
+- sv.rs.len);
+- LM_DBG("copying pvar value <%.*s> token size %d\n",
+- sv.rs.len, sv.rs.s, token.size);
+- result->len+=sv.rs.len;
++ memcpy(result->s + result->len, sv.rs.s, sv.rs.len);
++ LM_DBG("copying pvar value <%.*s> token size %d\n", sv.rs.len,
++ sv.rs.s, token.size);
++ result->len += sv.rs.len;
+ offset += token.size;
+ break;
+ default:
+@@ -552,12 +561,12 @@ int rule_translate(sip_msg_t *msg, str *
+ repl_nb++;
+ }
+ /* anything left? */
+- if( repl_nb && offset < repl_comp->replacement.len){
++ if(repl_nb && offset < repl_comp->replacement.len) {
+ /*copy from the replacing string*/
+ size = repl_comp->replacement.len - offset;
+ memcpy(result->s + result->len, p + offset, size);
+- LM_DBG("copying leftover <%.*s> from replacing string\n",
+- size, p + offset);
++ LM_DBG("copying leftover <%.*s> from replacing string\n", size,
++ p + offset);
+ result->len += size;
+ }
+
+@@ -570,10 +579,10 @@ error:
+ return -1;
+ }
+
+-#define DP_MAX_ATTRS_LEN 255
+-static char dp_attrs_buf[DP_MAX_ATTRS_LEN+1];
+-int dp_translate_helper(sip_msg_t *msg, str *input, str *output, dpl_id_p idp,
+- str *attrs)
++#define DP_MAX_ATTRS_LEN 255
++static char dp_attrs_buf[DP_MAX_ATTRS_LEN + 1];
++int dp_translate_helper(
++ sip_msg_t *msg, str *input, str *output, dpl_id_p idp, str *attrs)
+ {
+ dpl_node_p rulep;
+ dpl_index_p indexp;
+@@ -588,70 +597,70 @@ int dp_translate_helper(sip_msg_t *msg,
+ }
+
+ user_len = input->len;
+- for(indexp = idp->first_index; indexp!=NULL; indexp = indexp->next)
+- if(!indexp->len || (indexp->len!=0 && indexp->len == user_len) )
++ for(indexp = idp->first_index; indexp != NULL; indexp = indexp->next)
++ if(!indexp->len || (indexp->len != 0 && indexp->len == user_len))
+ break;
+
+- if(!indexp || (indexp!= NULL && !indexp->first_rule)){
++ if(!indexp || (indexp != NULL && !indexp->first_rule)) {
+ LM_DBG("no rule for len %i\n", input->len);
+ return -1;
+ }
+
+ search_rule:
+- for(rulep=indexp->first_rule; rulep!=NULL; rulep= rulep->next) {
++ for(rulep = indexp->first_rule; rulep != NULL; rulep = rulep->next) {
+ switch(rulep->matchop) {
+
+ case DP_REGEX_OP:
+- LM_DBG("regex operator testing over [%.*s]\n",
+- input->len, input->s);
+- if(rulep->tflags&DP_TFLAGS_PV_MATCH) {
++ LM_DBG("regex operator testing over [%.*s]\n", input->len,
++ input->s);
++ if(rulep->tflags & DP_TFLAGS_PV_MATCH) {
+ re_list = dpl_dynamic_pcre_list(msg, &rulep->match_exp);
+- if(re_list==NULL) {
++ if(re_list == NULL) {
+ /* failed to compile dynamic pcre -- ignore */
+ LM_DBG("failed to compile dynamic pcre[%.*s]\n",
+- rulep->match_exp.len, rulep->match_exp.s);
++ rulep->match_exp.len, rulep->match_exp.s);
+ continue;
+ }
+ rez = -1;
+ do {
+- if(rez<0) {
+- rez = pcre_exec(re_list->re, NULL, input->s, input->len,
+- 0, 0, NULL, 0);
++ if(rez < 0) {
++ rez = pcre_exec(re_list->re, NULL, input->s,
++ input->len, 0, 0, NULL, 0);
+ LM_DBG("match check: [%.*s] %d\n",
+- re_list->expr.len, re_list->expr.s, rez);
+- }
+- else LM_DBG("match check skipped: [%.*s] %d\n",
+- re_list->expr.len, re_list->expr.s, rez);
++ re_list->expr.len, re_list->expr.s, rez);
++ } else
++ LM_DBG("match check skipped: [%.*s] %d\n",
++ re_list->expr.len, re_list->expr.s, rez);
+ rt = re_list->next;
+ pcre_free(re_list->re);
+ pkg_free(re_list);
+ re_list = rt;
+ } while(re_list);
+ } else {
+- rez = pcre_exec(rulep->match_comp, NULL, input->s, input->len,
+- 0, 0, NULL, 0);
++ rez = pcre_exec(rulep->match_comp, NULL, input->s,
++ input->len, 0, 0, NULL, 0);
+ }
+ break;
+
+ case DP_EQUAL_OP:
+ LM_DBG("equal operator testing\n");
+- if(rulep->match_exp.s==NULL
++ if(rulep->match_exp.s == NULL
+ || rulep->match_exp.len != input->len) {
+ rez = -1;
+ } else {
+ rez = strncmp(rulep->match_exp.s, input->s, input->len);
+- rez = (rez==0)?0:-1;
++ rez = (rez == 0) ? 0 : -1;
+ }
+ break;
+
+ case DP_FNMATCH_OP:
+ LM_DBG("fnmatch operator testing\n");
+- if(rulep->match_exp.s!=NULL) {
++ if(rulep->match_exp.s != NULL) {
+ b = input->s[input->len];
+ input->s[input->len] = '\0';
+ rez = fnmatch(rulep->match_exp.s, input->s, 0);
+ input->s[input->len] = b;
+- rez = (rez==0)?0:-1;
++ rez = (rez == 0) ? 0 : -1;
+ } else {
+ rez = -1;
+ }
+@@ -665,8 +674,8 @@ search_rule:
+ goto repl;
+ }
+ /*test the rules with len 0*/
+- if(indexp->len){
+- for(indexp = indexp->next; indexp!=NULL; indexp = indexp->next)
++ if(indexp->len) {
++ for(indexp = indexp->next; indexp != NULL; indexp = indexp->next)
+ if(!indexp->len)
+ break;
+ if(indexp)
+@@ -677,63 +686,61 @@ search_rule:
+ return -1;
+
+ repl:
+- LM_DBG("found a matching rule %p: pr %i, match_exp %.*s\n",
+- rulep, rulep->pr, rulep->match_exp.len, rulep->match_exp.s);
++ LM_DBG("found a matching rule %p: pr %i, match_exp %.*s\n", rulep,
++ rulep->pr, rulep->match_exp.len, rulep->match_exp.s);
+
+ if(attrs) {
+ attrs->len = 0;
+ attrs->s = 0;
+- if(rulep->attrs.len>0) {
+- LM_DBG("the rule's attrs are %.*s\n",
+- rulep->attrs.len, rulep->attrs.s);
++ if(rulep->attrs.len > 0) {
++ LM_DBG("the rule's attrs are %.*s\n", rulep->attrs.len,
++ rulep->attrs.s);
+ if(rulep->attrs.len >= DP_MAX_ATTRS_LEN) {
+ LM_ERR("out of memory for attributes\n");
+ return -1;
+ }
+ attrs->s = dp_attrs_buf;
+- memcpy(attrs->s, rulep->attrs.s, rulep->attrs.len*sizeof(char));
++ memcpy(attrs->s, rulep->attrs.s, rulep->attrs.len * sizeof(char));
+ attrs->len = rulep->attrs.len;
+ attrs->s[attrs->len] = '\0';
+
+- LM_DBG("the copied attributes are: %.*s\n",
+- attrs->len, attrs->s);
++ LM_DBG("the copied attributes are: %.*s\n", attrs->len, attrs->s);
+ }
+ }
+ if(!output) {
+ return 0;
+ }
+- if(rulep->tflags&DP_TFLAGS_PV_SUBST) {
++ if(rulep->tflags & DP_TFLAGS_PV_SUBST) {
+ re_list = dpl_dynamic_pcre_list(msg, &rulep->subst_exp);
+- if(re_list==NULL) {
++ if(re_list == NULL) {
+ /* failed to compile dynamic pcre -- ignore */
+ LM_DBG("failed to compile dynamic pcre[%.*s]\n",
+- rulep->subst_exp.len, rulep->subst_exp.s);
++ rulep->subst_exp.len, rulep->subst_exp.s);
+ return -1;
+ }
+ rez = -1;
+ do {
+- if(rez<0) {
++ if(rez < 0) {
+ rez = rule_translate(msg, input, rulep, re_list->re, output);
+- LM_DBG("subst check: [%.*s] %d\n",
+- re_list->expr.len, re_list->expr.s, rez);
+- }
+- else LM_DBG("subst check skipped: [%.*s] %d\n",
+- re_list->expr.len, re_list->expr.s, rez);
++ LM_DBG("subst check: [%.*s] %d\n", re_list->expr.len,
++ re_list->expr.s, rez);
++ } else
++ LM_DBG("subst check skipped: [%.*s] %d\n", re_list->expr.len,
++ re_list->expr.s, rez);
+ rt = re_list->next;
+ pcre_free(re_list->re);
+ pkg_free(re_list);
+ re_list = rt;
+ } while(re_list);
+- if(rez<0) {
++ if(rez < 0) {
+ LM_ERR("the string %.*s matched "
+- "the match_exp %.*s but not the subst_exp %.*s!\n",
+- input->len, input->s,
+- rulep->match_exp.len, rulep->match_exp.s,
+- rulep->subst_exp.len, rulep->subst_exp.s);
++ "the match_exp %.*s but not the subst_exp %.*s!\n",
++ input->len, input->s, rulep->match_exp.len,
++ rulep->match_exp.s, rulep->subst_exp.len,
++ rulep->subst_exp.s);
+ }
+- }
+- else {
+- if(rule_translate(msg, input, rulep, rulep->subst_comp, output)!=0){
++ } else {
++ if(rule_translate(msg, input, rulep, rulep->subst_comp, output) != 0) {
+ LM_ERR("could not build the output\n");
+ return -1;
+ }
--- /dev/null
+From 374227b15ff7fbed8660beb93d52da15dcb4ba9e Mon Sep 17 00:00:00 2001
+From: Victor Seva <linuxmaniac@torreviejawireless.org>
+Date: Mon, 21 Aug 2023 12:27:43 +0200
+Subject: [PATCH] dialplan: migrate to pcre2
+
+---
+ src/modules/dialplan/Makefile | 11 +---
+ src/modules/dialplan/dialplan.c | 5 ++
+ src/modules/dialplan/dialplan.h | 20 ++++---
+ src/modules/dialplan/dp_db.c | 103 +++++++++++++++++++-------------
+ src/modules/dialplan/dp_repl.c | 56 +++++++++++------
+ 5 files changed, 121 insertions(+), 74 deletions(-)
+
+--- a/src/modules/dialplan/Makefile
++++ b/src/modules/dialplan/Makefile
+@@ -6,20 +6,15 @@ auto_gen=
+ NAME=dialplan.so
+
+ ifeq ($(CROSS_COMPILE),)
+-PCRE_BUILDER = $(shell \
+- if pkg-config --exists libcre; then \
+- echo 'pkg-config libpcre'; \
+- else \
+- which pcre-config; \
+- fi)
++PCRE_BUILDER = $(shell command -v pcre2-config)
+ endif
+
+ ifeq ($(PCRE_BUILDER),)
+ PCREDEFS=-I$(LOCALBASE)/include
+- PCRELIBS=-L$(LOCALBASE)/lib -lpcre
++ PCRELIBS=-L$(LOCALBASE)/lib -lpcre2-8
+ else
+ PCREDEFS = $(shell $(PCRE_BUILDER) --cflags)
+- PCRELIBS = $(shell $(PCRE_BUILDER) --libs)
++ PCRELIBS = $(shell $(PCRE_BUILDER) --libs8)
+ endif
+ DEFS+=$(PCREDEFS)
+ LIBS=$(PCRELIBS)
+--- a/src/modules/dialplan/dialplan.c
++++ b/src/modules/dialplan/dialplan.c
+@@ -5,6 +5,8 @@
+ *
+ * Copyright (C) 2014 Olle E. Johansson, Edvina AB
+ *
++ * Copyright (C) 2023 Victor Seva
++ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio is free software; you can redistribute it and/or modify
+@@ -79,6 +81,9 @@ static int ki_dp_translate_vars(
+ int dp_replace_fixup(void **param, int param_no);
+ int dp_replace_fixup_free(void **param, int param_no);
+
++pcre2_general_context *dpl_gctx = NULL;
++pcre2_compile_context *dpl_ctx = NULL;
++
+ str dp_attr_pvar_s = STR_NULL;
+ pv_spec_t *dp_attr_pvar = NULL;
+
+--- a/src/modules/dialplan/dialplan.h
++++ b/src/modules/dialplan/dialplan.h
+@@ -13,8 +13,8 @@
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+@@ -30,7 +30,8 @@
+ #ifndef _DP_DIALPLAN_H
+ #define _DP_DIALPLAN_H
+
+-#include <pcre.h>
++#define PCRE2_CODE_UNIT_WIDTH 8
++#include <pcre2.h>
+ #include "../../core/pvar.h"
+ #include "../../core/parser/msg_parser.h"
+
+@@ -43,6 +44,9 @@
+ #define DP_TFLAGS_PV_MATCH (1 << 0)
+ #define DP_TFLAGS_PV_SUBST (1 << 1)
+
++extern pcre2_general_context *dpl_gctx;
++extern pcre2_compile_context *dpl_ctx;
++
+ typedef struct dpl_node
+ {
+ int dpid; /* dialplan id */
+@@ -52,8 +56,8 @@ typedef struct dpl_node
+ str match_exp; /* match-first string */
+ str subst_exp; /* match string with subtitution groupping */
+ str repl_exp; /* replacement expression string */
+- pcre *match_comp; /* compiled matching expression */
+- pcre *subst_comp; /* compiled substitution expression */
++ pcre2_code *match_comp; /* compiled matching expression */
++ pcre2_code *subst_comp; /* compiled substitution expression */
+ struct subst_expr *repl_comp; /* compiled replacement */
+ str attrs; /* attributes string */
+ unsigned int tflags; /* flags for type of values for matching */
+@@ -103,8 +107,8 @@ struct subst_expr *repl_exp_parse(str su
+ void repl_expr_free(struct subst_expr *se);
+ int dp_translate_helper(
+ sip_msg_t *msg, str *user_name, str *repl_user, dpl_id_p idp, str *);
+-int rule_translate(
+- sip_msg_t *msg, str *instr, dpl_node_t *rule, pcre *subst_comp, str *);
++int rule_translate(sip_msg_t *msg, str *instr, dpl_node_t *rule,
++ pcre2_code *subst_comp, str *);
+
+-pcre *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype);
++pcre2_code *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype);
+ #endif
+--- a/src/modules/dialplan/dp_db.c
++++ b/src/modules/dialplan/dp_db.c
+@@ -196,11 +196,31 @@ void dp_disconnect_db(void)
+ }
+ }
+
++static void *pcre2_malloc(size_t size, void *ext)
++{
++ return shm_malloc(size);
++}
++
++static void pcre2_free(void *ptr, void *ext)
++{
++ shm_free(ptr);
++ ptr = NULL;
++}
+
+ int init_data(void)
+ {
+ int *p;
+
++ if((dpl_gctx = pcre2_general_context_create(pcre2_malloc, pcre2_free, NULL))
++ == NULL) {
++ LM_ERR("pcre2 general context creation failed\n");
++ return -1;
++ }
++ if((dpl_ctx = pcre2_compile_context_create(dpl_gctx)) == NULL) {
++ LM_ERR("pcre2 compile context creation failed\n");
++ return -1;
++ }
++
+ dp_rules_hash = (dpl_id_p *)shm_malloc(2 * sizeof(dpl_id_p));
+ if(!dp_rules_hash) {
+ LM_ERR("out of shm memory\n");
+@@ -227,6 +247,14 @@ int init_data(void)
+
+ void destroy_data(void)
+ {
++ if(dpl_ctx) {
++ pcre2_compile_context_free(dpl_ctx);
++ }
++
++ if(dpl_gctx) {
++ pcre2_general_context_free(dpl_gctx);
++ }
++
+ if(dp_rules_hash) {
+ destroy_hash(0);
+ destroy_hash(1);
+@@ -373,55 +401,50 @@ int dpl_str_to_shm(str src, str *dest, i
+
+
+ /* Compile pcre pattern
+- * if mtype==0 - return pointer to shm copy of result
+- * if mtype==1 - return pcre pointer that has to be pcre_free() */
+-pcre *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype)
+-{
+- pcre *re, *result;
+- const char *error;
+- int rc, err_offset;
+- size_t size;
++ * if mtype==0 - return pointer using shm
++ * if mtype==1 - return pcre2_code pointer that has to be pcre2_code_free() */
++pcre2_code *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype)
++{
++ pcre2_code *re;
++ int pcre_error_num = 0;
++ char pcre_error[128];
++ size_t pcre_erroffset;
++ int rc;
+
+- re = pcre_compile(pattern, 0, &error, &err_offset, NULL);
++ re = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, 0,
++ &pcre_error_num, &pcre_erroffset, mtype == 0 ? dpl_ctx : NULL);
+ if(re == NULL) {
+- LM_ERR("PCRE compilation of '%s' failed at offset %d: %s\n", pattern,
+- err_offset, error);
+- return (pcre *)0;
+- }
+- rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size);
+- if(rc != 0) {
+- pcre_free(re);
+- LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n",
+- pattern, rc);
+- return (pcre *)0;
++ switch(pcre2_get_error_message(
++ pcre_error_num, (PCRE2_UCHAR *)pcre_error, 128)) {
++ case PCRE2_ERROR_NOMEMORY:
++ snprintf(pcre_error, 128,
++ "unknown error[%d]: pcre2 error buffer too small",
++ pcre_error_num);
++ break;
++ case PCRE2_ERROR_BADDATA:
++ snprintf(pcre_error, 128, "unknown pcre2 error[%d]",
++ pcre_error_num);
++ break;
++ }
++ LM_ERR("PCRE compilation of '%s' failed at offset %zu: %s\n", pattern,
++ pcre_erroffset, pcre_error);
++ return NULL;
+ }
+- rc = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, cap_cnt);
++ rc = pcre2_pattern_info(re, PCRE2_INFO_CAPTURECOUNT, cap_cnt);
+ if(rc != 0) {
+- pcre_free(re);
++ pcre2_code_free(re);
+ LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n",
+ pattern, rc);
+- return (pcre *)0;
+- }
+- if(mtype == 0) {
+- result = (pcre *)shm_malloc(size);
+- if(result == NULL) {
+- pcre_free(re);
+- LM_ERR("not enough shared memory for compiled PCRE pattern\n");
+- return (pcre *)0;
+- }
+- memcpy(result, re, size);
+- pcre_free(re);
+- return result;
+- } else {
+- return re;
++ return NULL;
+ }
++ return re;
+ }
+
+
+ /*compile the expressions, and if ok, build the rule */
+ dpl_node_t *build_rule(db_val_t *values)
+ {
+- pcre *match_comp, *subst_comp;
++ pcre2_code *match_comp, *subst_comp;
+ struct subst_expr *repl_comp;
+ dpl_node_t *new_rule;
+ str match_exp, subst_exp, repl_exp, attrs;
+@@ -544,9 +567,9 @@ dpl_node_t *build_rule(db_val_t *values)
+
+ err:
+ if(match_comp)
+- shm_free(match_comp);
++ pcre2_code_free(match_comp);
+ if(subst_comp)
+- shm_free(subst_comp);
++ pcre2_code_free(subst_comp);
+ if(repl_comp)
+ repl_expr_free(repl_comp);
+ if(new_rule)
+@@ -692,10 +715,10 @@ void destroy_rule(dpl_node_t *rule)
+ LM_DBG("destroying rule with priority %i\n", rule->pr);
+
+ if(rule->match_comp)
+- shm_free(rule->match_comp);
++ pcre2_code_free(rule->match_comp);
+
+ if(rule->subst_comp)
+- shm_free(rule->subst_comp);
++ pcre2_code_free(rule->subst_comp);
+
+ /*destroy repl_exp*/
+ if(rule->repl_comp)
+--- a/src/modules/dialplan/dp_repl.c
++++ b/src/modules/dialplan/dp_repl.c
+@@ -15,8 +15,8 @@
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+@@ -38,7 +38,7 @@
+
+ typedef struct dpl_dyn_pcre
+ {
+- pcre *re;
++ pcre2_code *re;
+ int cnt;
+ str expr;
+
+@@ -186,9 +186,10 @@ int dpl_detect_avp_indx(const pv_elem_p
+ return 0;
+ }
+
+-pcre *dpl_dyn_pcre_comp(sip_msg_t *msg, str *expr, str *vexpr, int *cap_cnt)
++pcre2_code *dpl_dyn_pcre_comp(
++ sip_msg_t *msg, str *expr, str *vexpr, int *cap_cnt)
+ {
+- pcre *re = NULL;
++ pcre2_code *re = NULL;
+ int ccnt = 0;
+
+ if(expr == NULL || expr->s == NULL || expr->len <= 0 || vexpr == NULL
+@@ -225,7 +226,7 @@ dpl_dyn_pcre_p dpl_dynamic_pcre_list(sip
+ dpl_dyn_pcre_p rt = NULL;
+ struct str_list *l = NULL;
+ struct str_list *t = NULL;
+- pcre *re = NULL;
++ pcre2_code *re = NULL;
+ int cnt = 0;
+ str vexpr = STR_NULL;
+
+@@ -294,7 +295,7 @@ error:
+ while(re_list) {
+ rt = re_list->next;
+ if(re_list->re)
+- pcre_free(re_list->re);
++ pcre2_code_free(re_list->re);
+ pkg_free(re_list);
+ re_list = rt;
+ }
+@@ -400,15 +401,16 @@ error:
+ #define MAX_PHONE_NB_DIGITS 127
+ static char dp_output_buf[MAX_PHONE_NB_DIGITS + 1];
+ int rule_translate(sip_msg_t *msg, str *instr, dpl_node_t *rule,
+- pcre *subst_comp, str *result)
++ pcre2_code *subst_comp, str *result)
+ {
+ int repl_nb, offset, match_nb, rc, cap_cnt;
+ struct replace_with token;
+ struct subst_expr *repl_comp;
++ pcre2_match_data *pcre_md = NULL;
+ str match;
+ pv_value_t sv;
+ str *uri;
+- int ovector[3 * (MAX_REPLACE_WITH + 1)];
++ PCRE2_SIZE *ovector = NULL;
+ char *p;
+ int size;
+
+@@ -424,7 +426,7 @@ int rule_translate(sip_msg_t *msg, str *
+
+ if(subst_comp) {
+ /*just in case something went wrong at load time*/
+- rc = pcre_fullinfo(subst_comp, NULL, PCRE_INFO_CAPTURECOUNT, &cap_cnt);
++ rc = pcre2_pattern_info(subst_comp, PCRE2_INFO_CAPTURECOUNT, &cap_cnt);
+ if(rc != 0) {
+ LM_ERR("pcre_fullinfo on compiled pattern yielded error: %d\n", rc);
+ return -1;
+@@ -441,15 +443,19 @@ int rule_translate(sip_msg_t *msg, str *
+ }
+
+ /*search for the pattern from the compiled subst_exp*/
+- if(pcre_exec(subst_comp, NULL, instr->s, instr->len, 0, 0, ovector,
+- 3 * (MAX_REPLACE_WITH + 1))
++ pcre_md = pcre2_match_data_create_from_pattern(subst_comp, NULL);
++ if(pcre2_match(subst_comp, (PCRE2_SPTR)instr->s, (PCRE2_SIZE)instr->len,
++ 0, 0, pcre_md, NULL)
+ <= 0) {
+ LM_DBG("the string %.*s matched "
+ "the match_exp %.*s but not the subst_exp %.*s!\n",
+ instr->len, instr->s, rule->match_exp.len,
+ rule->match_exp.s, rule->subst_exp.len, rule->subst_exp.s);
++ if(pcre_md)
++ pcre2_match_data_free(pcre_md);
+ return -1;
+ }
++ ovector = pcre2_get_ovector_pointer(pcre_md);
+ }
+
+ /*simply copy from the replacing string*/
+@@ -463,6 +469,8 @@ int rule_translate(sip_msg_t *msg, str *
+ memcpy(result->s, repl_comp->replacement.s, repl_comp->replacement.len);
+ result->len = repl_comp->replacement.len;
+ result->s[result->len] = '\0';
++ if(pcre_md)
++ pcre2_match_data_free(pcre_md);
+ return 0;
+ }
+
+@@ -571,11 +579,15 @@ int rule_translate(sip_msg_t *msg, str *
+ }
+
+ result->s[result->len] = '\0';
++ if(pcre_md)
++ pcre2_match_data_free(pcre_md);
+ return 0;
+
+ error:
+ result->s = 0;
+ result->len = 0;
++ if(pcre_md)
++ pcre2_match_data_free(pcre_md);
+ return -1;
+ }
+
+@@ -584,6 +596,7 @@ static char dp_attrs_buf[DP_MAX_ATTRS_LE
+ int dp_translate_helper(
+ sip_msg_t *msg, str *input, str *output, dpl_id_p idp, str *attrs)
+ {
++ pcre2_match_data *pcre_md = NULL;
+ dpl_node_p rulep;
+ dpl_index_p indexp;
+ int user_len, rez;
+@@ -624,21 +637,28 @@ search_rule:
+ rez = -1;
+ do {
+ if(rez < 0) {
+- rez = pcre_exec(re_list->re, NULL, input->s,
+- input->len, 0, 0, NULL, 0);
++ pcre_md = pcre2_match_data_create_from_pattern(
++ re_list->re, NULL);
++ rez = pcre2_match(re_list->re, (PCRE2_SPTR)input->s,
++ (PCRE2_SIZE)input->len, 0, 0, pcre_md,
++ NULL);
+ LM_DBG("match check: [%.*s] %d\n",
+ re_list->expr.len, re_list->expr.s, rez);
+ } else
+ LM_DBG("match check skipped: [%.*s] %d\n",
+ re_list->expr.len, re_list->expr.s, rez);
+ rt = re_list->next;
+- pcre_free(re_list->re);
++ pcre2_match_data_free(pcre_md);
++ pcre2_code_free(re_list->re);
+ pkg_free(re_list);
+ re_list = rt;
+ } while(re_list);
+ } else {
+- rez = pcre_exec(rulep->match_comp, NULL, input->s,
+- input->len, 0, 0, NULL, 0);
++ pcre_md = pcre2_match_data_create_from_pattern(
++ rulep->match_comp, NULL);
++ rez = pcre2_match(rulep->match_comp, (PCRE2_SPTR)input->s,
++ (PCRE2_SIZE)input->len, 0, 0, pcre_md, 0);
++ pcre2_match_data_free(pcre_md);
+ }
+ break;
+
+@@ -728,7 +748,7 @@ repl:
+ LM_DBG("subst check skipped: [%.*s] %d\n", re_list->expr.len,
+ re_list->expr.s, rez);
+ rt = re_list->next;
+- pcre_free(re_list->re);
++ pcre2_code_free(re_list->re);
+ pkg_free(re_list);
+ re_list = rt;
+ } while(re_list);
--- /dev/null
+From ecc2c9e54fa8f24c1e96860c1f59b43f2e1e8b7a Mon Sep 17 00:00:00 2001
+From: Victor Seva <linuxmaniac@torreviejawireless.org>
+Date: Wed, 17 May 2023 16:36:55 +0200
+Subject: [PATCH] lcr: clang-format for coherent indentation and coding style
+
+---
+ src/modules/lcr/lcr_mod.c | 125 +++++++++++++++++++++-----------------
+ src/modules/lcr/lcr_rpc.c | 65 ++++++++++----------
+ 2 files changed, 102 insertions(+), 88 deletions(-)
+
+--- a/src/modules/lcr/lcr_mod.c
++++ b/src/modules/lcr/lcr_mod.c
+@@ -259,7 +259,8 @@ static int inactivate_gw(struct sip_msg
+ static int defunct_gw(struct sip_msg *_m, char *_s1, char *_s2);
+ static int from_gw_1(struct sip_msg *_m, char *_s1, char *_s2);
+ static int from_gw_3(struct sip_msg *_m, char *_s1, char *_s2, char *_s3);
+-static int from_gw_4(struct sip_msg *_m, char *_s1, char *_s2, char *_s3, char *_s4);
++static int from_gw_4(
++ struct sip_msg *_m, char *_s1, char *_s2, char *_s3, char *_s4);
+ static int from_any_gw_0(struct sip_msg *_m, char *_s1, char *_s2);
+ static int from_any_gw_2(struct sip_msg *_m, char *_s1, char *_s2);
+ static int from_any_gw_3(struct sip_msg *_m, char *_s1, char *_s2, char *_s3);
+@@ -554,7 +555,8 @@ static int mod_init(void)
+ LM_ERR("malformed or non AVP definition <%s>\n", rule_id_avp_param);
+ return -1;
+ }
+- if(pv_get_avp_name(0, &(avp_spec->pvp), &rule_id_avp, &avp_flags) != 0) {
++ if(pv_get_avp_name(0, &(avp_spec->pvp), &rule_id_avp, &avp_flags)
++ != 0) {
+ LM_ERR("invalid AVP definition <%s>\n", rule_id_avp_param);
+ return -1;
+ }
+@@ -680,18 +682,21 @@ static int mod_init(void)
+ LM_ERR("unable to open database connection\n");
+ return -1;
+ }
+- if(db_check_table_version(&lcr_dbf, dbh, &lcr_rule_table,
+- LCR_RULE_TABLE_VERSION) < 0) {
++ if(db_check_table_version(
++ &lcr_dbf, dbh, &lcr_rule_table, LCR_RULE_TABLE_VERSION)
++ < 0) {
+ DB_TABLE_VERSION_ERROR(lcr_rule_table);
+ goto dberror;
+ }
+ if(db_check_table_version(&lcr_dbf, dbh, &lcr_rule_target_table,
+- LCR_RULE_TARGET_TABLE_VERSION) < 0) {
++ LCR_RULE_TARGET_TABLE_VERSION)
++ < 0) {
+ DB_TABLE_VERSION_ERROR(lcr_rule_target_table);
+ goto dberror;
+ }
+- if (db_check_table_version(&lcr_dbf, dbh, &lcr_gw_table,
+- LCR_GW_TABLE_VERSION) < 0) {
++ if(db_check_table_version(
++ &lcr_dbf, dbh, &lcr_gw_table, LCR_GW_TABLE_VERSION)
++ < 0) {
+ DB_TABLE_VERSION_ERROR(lcr_gw_table);
+ goto dberror;
+ }
+@@ -923,20 +928,24 @@ static int comp_gws(const void *_g1, con
+ /*
+ * Compare a gateway using IP address and the src port
+ */
+-static struct gw_info * find_gateway_by_ip_and_port(struct gw_info * gw, struct gw_info * gws) {
++static struct gw_info *find_gateway_by_ip_and_port(
++ struct gw_info *gw, struct gw_info *gws)
++{
+ int tmp = 0, gw_index = 0, i;
+
+- for (i = 1; i <= gws[0].ip_addr.u.addr32[0]; i++) {
+- tmp = memcmp(gws[i].ip_addr.u.addr, gw->ip_addr.u.addr, gws[i].ip_addr.len);
+- if (gws[i].ip_addr.af == gw->ip_addr.af &&
+- gws[i].ip_addr.len == gw->ip_addr.len &&
+- tmp == 0 && /* a comparison of the IP address value */
+- gws[i].port == gw->port) {
+- gw_index = i;
+- break;
++ for(i = 1; i <= gws[0].ip_addr.u.addr32[0]; i++) {
++ tmp = memcmp(
++ gws[i].ip_addr.u.addr, gw->ip_addr.u.addr, gws[i].ip_addr.len);
++ if(gws[i].ip_addr.af == gw->ip_addr.af
++ && gws[i].ip_addr.len == gw->ip_addr.len && tmp == 0
++ && /* a comparison of the IP address value */
++ gws[i].port == gw->port) {
++ gw_index = i;
++ break;
+ }
+ }
+- if (gw_index != 0) return &(gws[gw_index]);
++ if(gw_index != 0)
++ return &(gws[gw_index]);
+
+ return NULL;
+ }
+@@ -1074,7 +1083,7 @@ static int insert_gws(db1_res_t *res, st
+ row = RES_ROWS(res) + i;
+ if((VAL_NULL(ROW_VALUES(row) + 12) == 1)
+ || ((VAL_TYPE(ROW_VALUES(row) + 12) != DB1_INT)
+- && (VAL_TYPE(ROW_VALUES(row) + 12) != DB1_UINT))) {
++ && (VAL_TYPE(ROW_VALUES(row) + 12) != DB1_UINT))) {
+ LM_ERR("lcr_gw id at row <%u> is null or not int\n", i);
+ return 0;
+ }
+@@ -1501,8 +1510,7 @@ int reload_tables()
+
+ if((VAL_NULL(ROW_VALUES(row)) == 1)
+ || ((VAL_TYPE(ROW_VALUES(row)) != DB1_INT)
+- && (VAL_TYPE(ROW_VALUES(row))
+- != DB1_UINT))) {
++ && (VAL_TYPE(ROW_VALUES(row)) != DB1_UINT))) {
+ LM_ERR("lcr rule id at row <%u> is null or not int\n", i);
+ goto err;
+ }
+@@ -1544,8 +1552,8 @@ int reload_tables()
+
+ if((VAL_NULL(ROW_VALUES(row) + 3) == 1)
+ || ((VAL_TYPE(ROW_VALUES(row) + 3) != DB1_INT)
+- && (VAL_TYPE(ROW_VALUES(row) + 3)
+- != DB1_UINT))) {
++ && (VAL_TYPE(ROW_VALUES(row) + 3)
++ != DB1_UINT))) {
+ LM_ERR("lcr rule <%u> stopper is NULL or not int\n",
+ rule_id);
+ goto err;
+@@ -1558,8 +1566,8 @@ int reload_tables()
+
+ if((VAL_NULL(ROW_VALUES(row) + 4) == 1)
+ || ((VAL_TYPE(ROW_VALUES(row) + 4) != DB1_INT)
+- && (VAL_TYPE(ROW_VALUES(row) + 4)
+- != DB1_UINT))) {
++ && (VAL_TYPE(ROW_VALUES(row) + 4)
++ != DB1_UINT))) {
+ LM_ERR("lcr rule <%u> enabled is NULL or not int\n",
+ rule_id);
+ goto err;
+@@ -1769,8 +1777,7 @@ int reload_tables()
+ row = RES_ROWS(res) + i;
+ if((VAL_NULL(ROW_VALUES(row)) == 1)
+ || ((VAL_TYPE(ROW_VALUES(row)) != DB1_INT)
+- && (VAL_TYPE(ROW_VALUES(row))
+- != DB1_UINT))) {
++ && (VAL_TYPE(ROW_VALUES(row)) != DB1_UINT))) {
+ LM_ERR("lcr_rule_target rule_id at row <%u> is null "
+ "or not int\n",
+ i);
+@@ -1779,8 +1786,8 @@ int reload_tables()
+ rule_id = (unsigned int)VAL_INT(ROW_VALUES(row));
+ if((VAL_NULL(ROW_VALUES(row) + 1) == 1)
+ || ((VAL_TYPE(ROW_VALUES(row) + 1) != DB1_INT)
+- && (VAL_TYPE(ROW_VALUES(row) + 1)
+- != DB1_UINT))) {
++ && (VAL_TYPE(ROW_VALUES(row) + 1)
++ != DB1_UINT))) {
+ LM_ERR("lcr_rule_target gw_id at row <%u> is null "
+ "or not int\n",
+ i);
+@@ -1789,8 +1796,8 @@ int reload_tables()
+ gw_id = (unsigned int)VAL_INT(ROW_VALUES(row) + 1);
+ if((VAL_NULL(ROW_VALUES(row) + 2) == 1)
+ || ((VAL_TYPE(ROW_VALUES(row) + 2) != DB1_INT)
+- && (VAL_TYPE(ROW_VALUES(row) + 2)
+- != DB1_UINT))) {
++ && (VAL_TYPE(ROW_VALUES(row) + 2)
++ != DB1_UINT))) {
+ LM_ERR("lcr_rule_target priority at row <%u> is null "
+ "or not int\n",
+ i);
+@@ -1805,8 +1812,8 @@ int reload_tables()
+ }
+ if((VAL_NULL(ROW_VALUES(row) + 3) == 1)
+ || ((VAL_TYPE(ROW_VALUES(row) + 3) != DB1_INT)
+- && (VAL_TYPE(ROW_VALUES(row) + 3)
+- != DB1_UINT))) {
++ && (VAL_TYPE(ROW_VALUES(row) + 3)
++ != DB1_UINT))) {
+ LM_ERR("lcr_rule_target weight at row <%u> is null "
+ "or not int\n",
+ i);
+@@ -2087,10 +2094,10 @@ void add_gws_into_avps(struct gw_info *g
+ if(5 /* gw_index */ + 5 /* scheme */ + 4 /* strip */ + prefix_len
+ + tag_len + 1 /* @ */
+ + ((hostname_len > IP6_MAX_STR_SIZE + 2)
+- ? hostname_len
+- : IP6_MAX_STR_SIZE + 2)
++ ? hostname_len
++ : IP6_MAX_STR_SIZE + 2)
+ + 6 /* port */ + params_len /* params */
+- + 15 /* transport */ + 10 /* flags */
++ + 15 /* transport */ + 10 /* flags */
+ + 7 /* separators */
+ + 10 /* rule_id */
+ > MAX_URI_LEN) {
+@@ -2174,7 +2181,7 @@ int load_gws_dummy(int lcr_id, str *ruri
+ if((rule->from_uri_len != 0)
+ && (pcre_exec(rule->from_uri_re, NULL, from_uri->s,
+ from_uri->len, 0, 0, NULL, 0)
+- < 0))
++ < 0))
+ goto next;
+
+ if((from_uri->len > 0) && (rule->mt_tvalue_len > 0)) {
+@@ -2339,7 +2346,7 @@ static int ki_load_gws_furi(
+ if((rule->from_uri_len != 0)
+ && (pcre_exec(rule->from_uri_re, NULL, from_uri->s,
+ from_uri->len, 0, 0, NULL, 0)
+- < 0)) {
++ < 0)) {
+ LM_DBG("from uri <%.*s> did not match to from regex <%.*s>\n",
+ from_uri->len, from_uri->s, rule->from_uri_len,
+ rule->from_uri);
+@@ -2375,7 +2382,7 @@ static int ki_load_gws_furi(
+ if((rule->request_uri_len != 0)
+ && (pcre_exec(rule->request_uri_re, NULL, request_uri->s,
+ request_uri->len, 0, 0, NULL, 0)
+- < 0)) {
++ < 0)) {
+ LM_DBG("request uri <%.*s> did not match to request regex "
+ "<%.*s>\n",
+ request_uri->len, request_uri->s, rule->request_uri_len,
+@@ -2549,7 +2556,8 @@ static int generate_uris(struct sip_msg
+ return 0; /* No more gateways left */
+
+ decode_avp_value(gw_uri_val.s.s, gw_index, &scheme, &strip, &prefix,
+- &tmp_tag, addr, &hostname, &port, ¶ms, &transport, flags, rule_id);
++ &tmp_tag, addr, &hostname, &port, ¶ms, &transport, flags,
++ rule_id);
+
+ if(addr->af != 0) {
+ addr_str.s = ip_addr2a(addr);
+@@ -2560,8 +2568,8 @@ static int generate_uris(struct sip_msg
+
+ if(scheme.len + r_uri_user->len - strip + prefix.len + 1 /* @ */
+ + ((hostname.len > IP6_MAX_STR_SIZE + 2)
+- ? hostname.len
+- : IP6_MAX_STR_SIZE + 2)
++ ? hostname.len
++ : IP6_MAX_STR_SIZE + 2)
+ + 1 /* : */ + port.len + params.len + transport.len
+ + 1 /* null */
+ > MAX_URI_LEN) {
+@@ -2992,7 +3000,7 @@ static int ki_next_gw(sip_msg_t *_m)
+ if(rule_id_avp_param) {
+ val.n = rule_id;
+ add_avp(rule_id_avp_type, rule_id_avp, val);
+- LM_DBG("added rule_id_avp <%u>\n", (unsigned int)val.n);
++ LM_DBG("added rule_id_avp <%u>\n", (unsigned int)val.n);
+ }
+
+ /* Add index of selected gw to defunct gw AVP */
+@@ -3018,7 +3026,8 @@ static int next_gw(struct sip_msg *_m, c
+ * Checks if request comes from ip address of a gateway
+ */
+ static int do_from_gw(struct sip_msg *_m, unsigned int lcr_id,
+- struct ip_addr *src_addr, uri_transport transport, unsigned int src_port)
++ struct ip_addr *src_addr, uri_transport transport,
++ unsigned int src_port)
+ {
+ struct gw_info *res, gw, *gws;
+ int_str val;
+@@ -3032,18 +3041,20 @@ static int do_from_gw(struct sip_msg *_m
+ }
+
+ gw.ip_addr = *src_addr;
+- if (src_port != 0) {
++ if(src_port != 0) {
+ /* Search for gw based on its ip address and port */
+ gw.port = src_port;
+ res = find_gateway_by_ip_and_port(&gw, gws);
+ } else {
+ /* Search for gw based on its ip address */
+- res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr.u.addr32[0],
+- sizeof(struct gw_info), comp_gws);
++ res = (struct gw_info *)bsearch(&gw, &(gws[1]),
++ gws[0].ip_addr.u.addr32[0], sizeof(struct gw_info), comp_gws);
+ }
+
+ /* Store tag and flags and return result */
+- if((res != NULL) && ((transport == PROTO_NONE) || (res->transport_code == transport))) {
++ if((res != NULL)
++ && ((transport == PROTO_NONE)
++ || (res->transport_code == transport))) {
+ LM_DBG("request came from gw\n");
+ if(tag_avp_param) {
+ val.s.s = res->tag;
+@@ -3178,8 +3189,8 @@ static int from_gw_3(
+ return ki_from_gw_addr_port(_m, lcr_id, &addr_str, transport, 0);
+ }
+
+-static int from_gw_4(
+- struct sip_msg *_m, char *_lcr_id, char *_addr, char *_transport, char *_src_port)
++static int from_gw_4(struct sip_msg *_m, char *_lcr_id, char *_addr,
++ char *_transport, char *_src_port)
+ {
+ int lcr_id;
+ str addr_str;
+@@ -3202,7 +3213,7 @@ static int from_gw_4(
+ LM_ERR("invalid transport parameter %s\n", _lcr_id);
+ return -1;
+ }
+- tmp=0;
++ tmp = 0;
+ src_port = strtol(_src_port, &tmp, 10);
+ if((tmp == 0) || (*tmp) || (tmp == _src_port)) {
+ LM_ERR("invalid port parameter %s\n", _src_port);
+@@ -3243,8 +3254,8 @@ static int from_any_gw_0(struct sip_msg
+ * Checks if request comes from ip address of a gateway taking source
+ * IP address, transport protocol and source port from parameters.
+ */
+-static int ki_from_any_gw_addr_port(sip_msg_t *_m, str *addr_str, int transport,
+- int src_port)
++static int ki_from_any_gw_addr_port(
++ sip_msg_t *_m, str *addr_str, int transport, int src_port)
+ {
+ unsigned int i;
+ struct ip_addr *ip, src_addr;
+@@ -3307,7 +3318,8 @@ static int from_any_gw_2(struct sip_msg
+ return ki_from_any_gw_addr_port(_m, &addr_str, transport, 0);
+ }
+
+-static int from_any_gw_3(struct sip_msg *_m, char *_addr, char *_transport, char *_src_port)
++static int from_any_gw_3(
++ struct sip_msg *_m, char *_addr, char *_transport, char *_src_port)
+ {
+ str addr_str;
+ uri_transport transport;
+@@ -3323,7 +3335,7 @@ static int from_any_gw_3(struct sip_msg
+ LM_ERR("invalid transport parameter %s\n", _transport);
+ return -1;
+ }
+- tmp=0;
++ tmp = 0;
+ src_port = strtol(_src_port, &tmp, 10);
+ if((tmp == 0) || (*tmp) || (tmp == _src_port)) {
+ LM_ERR("invalid port parameter %s\n", _src_port);
+@@ -3355,8 +3367,9 @@ static int do_to_gw(struct sip_msg *_m,
+ sizeof(struct gw_info), comp_gws);
+
+ /* Return result */
+- if((res != NULL) && ((transport == PROTO_NONE)
+- || (res->transport_code == transport))) {
++ if((res != NULL)
++ && ((transport == PROTO_NONE)
++ || (res->transport_code == transport))) {
+ LM_DBG("request goes to gw\n");
+ return 1;
+ } else {
+--- a/src/modules/lcr/lcr_rpc.c
++++ b/src/modules/lcr/lcr_rpc.c
+@@ -48,7 +48,8 @@ static void reload(rpc_t *rpc, void *c)
+ static const char *dump_gws_doc[2] = {"Dump the contents of lcr_gws table.", 0};
+
+
+-static void dump_gw(rpc_t *rpc, void *st, struct gw_info *gw, unsigned int gw_index, unsigned int lcr_id)
++static void dump_gw(rpc_t *rpc, void *st, struct gw_info *gw,
++ unsigned int gw_index, unsigned int lcr_id)
+ {
+ str scheme, gw_name, hostname, params, transport;
+ str prefix, tag;
+@@ -72,14 +73,10 @@ static void dump_gw(rpc_t *rpc, void *st
+ break;
+ case AF_INET6:
+ rpc->struct_printf(st, "ip_addr", "%x:%x:%x:%x:%x:%x:%x:%x",
+- gw->ip_addr.u.addr16[0],
+- gw->ip_addr.u.addr16[1],
+- gw->ip_addr.u.addr16[2],
+- gw->ip_addr.u.addr16[3],
+- gw->ip_addr.u.addr16[4],
+- gw->ip_addr.u.addr16[5],
+- gw->ip_addr.u.addr16[6],
+- gw->ip_addr.u.addr16[7]);
++ gw->ip_addr.u.addr16[0], gw->ip_addr.u.addr16[1],
++ gw->ip_addr.u.addr16[2], gw->ip_addr.u.addr16[3],
++ gw->ip_addr.u.addr16[4], gw->ip_addr.u.addr16[5],
++ gw->ip_addr.u.addr16[6], gw->ip_addr.u.addr16[7]);
+ break;
+ case 0:
+ rpc->struct_add(st, "s", "ip_addr", "0.0.0.0");
+@@ -99,11 +96,10 @@ static void dump_gw(rpc_t *rpc, void *st
+ prefix.len = gw->prefix_len;
+ tag.s = gw->tag;
+ tag.len = gw->tag_len;
+- start = int2strbuf(
+- gw->defunct_until, &(buf[0]), INT2STR_MAX_LEN, &len);
+- rpc->struct_add(st, "dSSdds", "strip", gw->strip, "prefix",
+- &prefix, "tag", &tag, "flags", gw->flags, "state",
+- gw->state, "defunct_until", start);
++ start = int2strbuf(gw->defunct_until, &(buf[0]), INT2STR_MAX_LEN, &len);
++ rpc->struct_add(st, "dSSdds", "strip", gw->strip, "prefix", &prefix, "tag",
++ &tag, "flags", gw->flags, "state", gw->state, "defunct_until",
++ start);
+ }
+
+ static void dump_gws(rpc_t *rpc, void *c)
+@@ -119,7 +115,7 @@ static void dump_gws(rpc_t *rpc, void *c
+ gws = gw_pt[j];
+
+ for(i = 1; i <= gws[0].ip_addr.u.addr32[0]; i++) {
+- if (srec==NULL) {
++ if(srec == NULL) {
+ /* We create one array per lcr_id */
+ if(rpc->add(c, "{", &rec) < 0)
+ return;
+@@ -143,7 +139,7 @@ static void dump_rules(rpc_t *rpc, void
+ int i, j;
+ int _filter_by_prefix = 0;
+ int _lcr_id = 0;
+- str _prefix = {NULL,0};
++ str _prefix = {NULL, 0};
+ struct rule_info **rules, *rule;
+ struct target *t;
+ void *rec = NULL;
+@@ -151,29 +147,32 @@ static void dump_rules(rpc_t *rpc, void
+ void *st, *sst, *ssst;
+ str prefix, from_uri, request_uri;
+
+- if (rpc->scan(c, "d", &_lcr_id)>0) {
+- if (rpc->scan(c, ".S", &_prefix)>0) {
++ if(rpc->scan(c, "d", &_lcr_id) > 0) {
++ if(rpc->scan(c, ".S", &_prefix) > 0) {
+ _filter_by_prefix = 1;
+ }
+ }
+
+ for(j = 1; j <= lcr_count_param; j++) {
+
+- if (_lcr_id && _lcr_id!=j) continue;
++ if(_lcr_id && _lcr_id != j)
++ continue;
+
+ rules = rule_pt[j];
+
+ for(i = 0; i < lcr_rule_hash_size_param; i++) {
+ rule = rules[i];
+ while(rule) {
+- if (_filter_by_prefix && _prefix.len && _prefix.s) {
+- if (_prefix.len < rule->prefix_len ||
+- strncmp(_prefix.s, rule->prefix, rule->prefix_len)!=0) {
++ if(_filter_by_prefix && _prefix.len && _prefix.s) {
++ if(_prefix.len < rule->prefix_len
++ || strncmp(_prefix.s, rule->prefix,
++ rule->prefix_len)
++ != 0) {
+ rule = rule->next;
+ continue;
+ }
+ }
+- if (srec==NULL) {
++ if(srec == NULL) {
+ /* We create one array per lcr_id */
+ if(rpc->add(c, "{", &rec) < 0)
+ return;
+@@ -192,11 +191,11 @@ static void dump_rules(rpc_t *rpc, void
+ rule->rule_id, "prefix", &prefix, "from_uri", &from_uri,
+ "request_uri", &request_uri, "stopper", rule->stopper);
+ t = rule->targets;
+- if (t) {
+- if (rpc->struct_add(st, "[", "gw", &sst) < 0)
++ if(t) {
++ if(rpc->struct_add(st, "[", "gw", &sst) < 0)
+ return;
+ while(t) {
+- if (rpc->array_add(sst, "{", &ssst) < 0)
++ if(rpc->array_add(sst, "{", &ssst) < 0)
+ return;
+ rpc->struct_add(ssst, "ddd", "gw_index", t->gw_index,
+ "priority", t->priority, "weight", t->weight);
+@@ -210,10 +209,10 @@ static void dump_rules(rpc_t *rpc, void
+ /* Mark the end of rule array */
+ srec = NULL;
+
+- if (_filter_by_prefix)
++ if(_filter_by_prefix)
+ continue;
+ rule = rules[lcr_rule_hash_size_param];
+- if (rule) {
++ if(rule) {
+ if(rpc->struct_add(rec, "[", "prefix_len", &st) < 0)
+ return;
+ while(rule) {
+@@ -222,7 +221,8 @@ static void dump_rules(rpc_t *rpc, void
+ }
+ }
+ }
+- if (rec==NULL) rpc->fault(c, 404, "Empty reply");
++ if(rec == NULL)
++ rpc->fault(c, 404, "Empty reply");
+ }
+
+
+@@ -269,8 +269,9 @@ static void load_gws(rpc_t *rpc, void *c
+
+ ret = rpc->scan(c, "dS*SS", &lcr_id, &uri_user, &caller_uri, &request_uri);
+ if(ret == -1) {
+- rpc->fault(c, 400, "parameter error; if using cli, remember to prefix "
+- "numeric uri_user param value with 's:'");
++ rpc->fault(c, 400,
++ "parameter error; if using cli, remember to prefix "
++ "numeric uri_user param value with 's:'");
+ return;
+ }
+
+@@ -289,7 +290,7 @@ static void load_gws(rpc_t *rpc, void *c
+
+ gws = gw_pt[lcr_id];
+ for(j = 0; j < gw_count; j++) {
+- if (rec==NULL) {
++ if(rec == NULL) {
+ if(rpc->add(c, "[", &rec) < 0)
+ return;
+ }
--- /dev/null
+From 70a9ea2b1e5cceeaf050356e7baf00127a58567d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?=
+ =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= <git-dpa@aegee.org>
+Date: Mon, 8 May 2023 13:13:49 +0200
+Subject: [PATCH] lcr: typos
+
+---
+ src/modules/lcr/doc/lcr_admin.xml | 2 +-
+ src/modules/lcr/lcr_mod.c | 6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/src/modules/lcr/doc/lcr_admin.xml
++++ b/src/modules/lcr/doc/lcr_admin.xml
+@@ -1641,7 +1641,7 @@ if (to_any_gw("192.55.66.2", 1)) {
+ <para>
+ Causes lcr module to dump the contents of its
+ in-memory lcr_rule and lcr_rule_target tables.
+- Rules can be filetered by lcr_id or lcr_id and prefix.
++ Rules can be filtered by lcr_id or lcr_id and prefix.
+ The filters are passed as optional parameters.
+ </para>
+ <para>Parameters:</para>
+--- a/src/modules/lcr/lcr_mod.c
++++ b/src/modules/lcr/lcr_mod.c
+@@ -188,7 +188,7 @@ unsigned int lcr_gw_count_param = DEF_LC
+ /* can gws be defuncted */
+ static unsigned int defunct_capability_param = 0;
+
+-/* dont strip or tag param */
++/* don't strip or tag param */
+ static int dont_strip_or_prefix_flag_param = -1;
+
+ /* ping related params */
+@@ -846,7 +846,7 @@ static int comp_matched(const void *m1,
+ if(mi1->priority < mi2->priority)
+ return 1;
+ if(mi1->priority == mi2->priority) {
+- /* Sort by randomized weigth */
++ /* Sort by randomized weight */
+ if(mi1->weight > mi2->weight)
+ return 1;
+ if(mi1->weight == mi2->weight)
+@@ -863,7 +863,7 @@ static int comp_matched(const void *m1,
+ if(mi1->priority < mi2->priority)
+ return 1;
+ if(mi1->priority == mi2->priority) {
+- /* Sort by randomized weigth */
++ /* Sort by randomized weight */
+ if(mi1->weight > mi2->weight)
+ return 1;
+ if(mi1->weight == mi2->weight)
--- /dev/null
+From e3e2c41e8c46a13bad18dd40fd9e3540020dd5eb Mon Sep 17 00:00:00 2001
+From: Victor Seva <linuxmaniac@torreviejawireless.org>
+Date: Mon, 21 Aug 2023 13:30:36 +0200
+Subject: [PATCH] lcr: pcre2 migration
+
+---
+ src/modules/lcr/Makefile | 12 +--
+ src/modules/lcr/hash.c | 24 ++---
+ src/modules/lcr/hash.h | 10 +-
+ src/modules/lcr/lcr_mod.c | 187 +++++++++++++++++++++++++-------------
+ src/modules/lcr/lcr_mod.h | 8 +-
+ 5 files changed, 150 insertions(+), 91 deletions(-)
+
+--- a/src/modules/lcr/Makefile
++++ b/src/modules/lcr/Makefile
+@@ -9,20 +9,15 @@ auto_gen=
+ NAME=lcr.so
+
+ ifeq ($(CROSS_COMPILE),)
+-PCRE_BUILDER = $(shell \
+- if pkg-config --exists libcre; then \
+- echo 'pkg-config libpcre'; \
+- else \
+- which pcre-config; \
+- fi)
++PCRE_BUILDER = $(shell command -v pcre2-config)
+ endif
+
+ ifeq ($(PCRE_BUILDER),)
+ PCREDEFS=-I$(LOCALBASE)/include
+- PCRELIBS=-L$(LOCALBASE)/lib -lpcre
++ PCRELIBS=-L$(LOCALBASE)/lib -lpcre2-8
+ else
+ PCREDEFS = $(shell $(PCRE_BUILDER) --cflags)
+- PCRELIBS = $(shell $(PCRE_BUILDER) --libs)
++ PCRELIBS = $(shell $(PCRE_BUILDER) --libs8)
+ endif
+
+ DEFS+=$(PCREDEFS)
+@@ -31,4 +26,3 @@ LIBS+=$(PCRELIBS)
+ SERLIBPATH=../../lib
+ SER_LIBS+=$(SERLIBPATH)/srdb1/srdb1
+ include ../../Makefile.modules
+-
+--- a/src/modules/lcr/hash.c
++++ b/src/modules/lcr/hash.c
+@@ -15,8 +15,8 @@
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+@@ -36,10 +36,10 @@
+ /* Add lcr entry into hash table */
+ int rule_hash_table_insert(struct rule_info **hash_table, unsigned int lcr_id,
+ unsigned int rule_id, unsigned short prefix_len, char *prefix,
+- unsigned short from_uri_len, char *from_uri, pcre *from_uri_re,
++ unsigned short from_uri_len, char *from_uri, pcre2_code *from_uri_re,
+ unsigned short mt_tvalue_len, char *mt_tvalue,
+- unsigned short request_uri_len, char *request_uri, pcre *request_uri_re,
+- unsigned short stopper)
++ unsigned short request_uri_len, char *request_uri,
++ pcre2_code *request_uri_re, unsigned short stopper)
+ {
+ struct rule_info *rule;
+ str prefix_str;
+@@ -50,9 +50,9 @@ int rule_hash_table_insert(struct rule_i
+ if(rule == NULL) {
+ SHM_MEM_ERROR_FMT("for rule hash table entry\n");
+ if(from_uri_re)
+- shm_free(from_uri_re);
++ pcre2_code_free(from_uri_re);
+ if(request_uri_re)
+- shm_free(request_uri_re);
++ pcre2_code_free(request_uri_re);
+ return 0;
+ }
+ memset(rule, 0, sizeof(struct rule_info));
+@@ -99,9 +99,9 @@ int rule_hash_table_insert(struct rule_i
+ if(rid == NULL) {
+ PKG_MEM_ERROR_FMT("for rule_id hash table entry\n");
+ if(from_uri_re)
+- shm_free(from_uri_re);
++ pcre2_code_free(from_uri_re);
+ if(request_uri_re)
+- shm_free(request_uri_re);
++ pcre2_code_free(request_uri_re);
+ shm_free(rule);
+ return 0;
+ }
+@@ -180,7 +180,7 @@ int rule_hash_table_insert_target(struct
+ }
+
+
+-/*
++/*
+ * Return pointer to lcr hash table entry to which given prefix hashes to.
+ */
+ struct rule_info *rule_hash_table_lookup(
+@@ -209,10 +209,10 @@ void rule_hash_table_contents_free(struc
+ r = hash_table[i];
+ while(r) {
+ if(r->from_uri_re) {
+- shm_free(r->from_uri_re);
++ pcre2_code_free(r->from_uri_re);
+ }
+ if(r->request_uri_re)
+- shm_free(r->request_uri_re);
++ pcre2_code_free(r->request_uri_re);
+ t = r->targets;
+ while(t) {
+ next_t = t->next;
+--- a/src/modules/lcr/hash.h
++++ b/src/modules/lcr/hash.h
+@@ -15,8 +15,8 @@
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+@@ -34,10 +34,10 @@
+
+ int rule_hash_table_insert(struct rule_info **hash_table, unsigned int lcr_id,
+ unsigned int rule_id, unsigned short prefix_len, char *prefix,
+- unsigned short from_uri_len, char *from_uri, pcre *from_uri_re,
++ unsigned short from_uri_len, char *from_uri, pcre2_code *from_uri_re,
+ unsigned short mt_tvalue_len, char *mt_tvalue,
+- unsigned short request_uri_len, char *request_uri, pcre *request_uri_re,
+- unsigned short stopper);
++ unsigned short request_uri_len, char *request_uri,
++ pcre2_code *request_uri_re, unsigned short stopper);
+
+ int rule_hash_table_insert_target(struct rule_info **hash_table,
+ struct gw_info *gws, unsigned int rule_id, unsigned int gw_id,
+--- a/src/modules/lcr/lcr_mod.c
++++ b/src/modules/lcr/lcr_mod.c
+@@ -16,8 +16,8 @@
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+@@ -43,7 +43,8 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <arpa/inet.h>
+-#include <pcre.h>
++#define PCRE2_CODE_UNIT_WIDTH 8
++#include <pcre2.h>
+ #include "../../core/locking.h"
+ #include "../../core/sr_module.h"
+ #include "../../core/dprint.h"
+@@ -204,6 +205,9 @@ static unsigned int priority_ordering_pa
+ /* mtree tree name */
+ str mtree_param = {"lcr", 3};
+
++static pcre2_general_context *lcr_gctx = NULL;
++static pcre2_compile_context *lcr_ctx = NULL;
++
+ /*
+ * Other module types and variables
+ */
+@@ -364,7 +368,7 @@ static param_export_t params[] = {
+ * Module interface
+ */
+ struct module_exports exports = {
+- "lcr",
++ "lcr",
+ DEFAULT_DLFLAGS, /* dlopen flags */
+ cmds, /* Exported functions */
+ params, /* Exported parameters */
+@@ -422,6 +426,16 @@ static void lcr_db_close(void)
+ }
+ }
+
++static void *pcre2_malloc(size_t size, void *ext)
++{
++ return shm_malloc(size);
++}
++
++static void pcre2_free(void *ptr, void *ext)
++{
++ shm_free(ptr);
++ ptr = NULL;
++}
+
+ /*
+ * Module initialization function that is called before the main process forks
+@@ -703,7 +717,15 @@ static int mod_init(void)
+ lcr_db_close();
+
+ /* rule shared memory */
+-
++ if((lcr_gctx = pcre2_general_context_create(pcre2_malloc, pcre2_free, NULL))
++ == NULL) {
++ LM_ERR("pcre2 general context creation failed\n");
++ goto err;
++ }
++ if((lcr_ctx = pcre2_compile_context_create(lcr_gctx)) == NULL) {
++ LM_ERR("pcre2 compile context creation failed\n");
++ goto err;
++ }
+ /* rule hash table pointer table */
+ /* pointer at index 0 points to temp rule hash table */
+ rule_pt = (struct rule_info ***)shm_malloc(
+@@ -779,6 +801,12 @@ dberror:
+ lcr_db_close();
+
+ err:
++ if(lcr_ctx) {
++ pcre2_compile_context_free(lcr_ctx);
++ }
++ if(lcr_gctx) {
++ pcre2_general_context_free(lcr_gctx);
++ }
+ free_shared_memory();
+ return -1;
+ }
+@@ -794,7 +822,12 @@ static int child_init(int rank)
+ static void destroy(void)
+ {
+ lcr_db_close();
+-
++ if(lcr_ctx) {
++ pcre2_compile_context_free(lcr_ctx);
++ }
++ if(lcr_gctx) {
++ pcre2_general_context_free(lcr_gctx);
++ }
+ free_shared_memory();
+ }
+
+@@ -875,33 +908,32 @@ static int comp_matched(const void *m1,
+
+
+ /* Compile pattern into shared memory and return pointer to it. */
+-static pcre *reg_ex_comp(const char *pattern)
++static pcre2_code *reg_ex_comp(const char *pattern)
+ {
+- pcre *re, *result;
+- const char *error;
+- int rc, err_offset;
+- size_t size;
+-
+- re = pcre_compile(pattern, 0, &error, &err_offset, NULL);
+- if(re == NULL) {
+- LM_ERR("pcre compilation of '%s' failed at offset %d: %s\n", pattern,
+- err_offset, error);
+- return (pcre *)0;
+- }
+- rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size);
+- if(rc != 0) {
+- LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n",
+- pattern, rc);
+- return (pcre *)0;
+- }
+- result = (pcre *)shm_malloc(size);
++ pcre2_code *result;
++ int pcre_error_num = 0;
++ char pcre_error[128];
++ size_t pcre_erroffset;
++
++ result = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, 0,
++ &pcre_error_num, &pcre_erroffset, lcr_ctx);
+ if(result == NULL) {
+- pcre_free(re);
+- SHM_MEM_ERROR_FMT("for compiled PCRE pattern\n");
+- return (pcre *)0;
++ switch(pcre2_get_error_message(
++ pcre_error_num, (PCRE2_UCHAR *)pcre_error, 128)) {
++ case PCRE2_ERROR_NOMEMORY:
++ snprintf(pcre_error, 128,
++ "unknown error[%d]: pcre2 error buffer too small",
++ pcre_error_num);
++ break;
++ case PCRE2_ERROR_BADDATA:
++ snprintf(pcre_error, 128, "unknown pcre2 error[%d]",
++ pcre_error_num);
++ break;
++ }
++ LM_ERR("pcre compilation of '%s' failed at offset %zu: %s\n", pattern,
++ pcre_erroffset, pcre_error);
++ return NULL;
+ }
+- memcpy(result, re, size);
+- pcre_free(re);
+ return result;
+ }
+
+@@ -950,7 +982,7 @@ static struct gw_info *find_gateway_by_i
+ return NULL;
+ }
+
+-/*
++/*
+ * Insert gw info into index i or gws table
+ */
+ static int insert_gw(struct gw_info *gws, unsigned int i, unsigned int gw_id,
+@@ -1024,7 +1056,7 @@ static int insert_gw(struct gw_info *gws
+
+
+ /*
+- * Insert prefix_len into list pointed by last rule hash table entry
++ * Insert prefix_len into list pointed by last rule hash table entry
+ * if not there already. Keep list in decending prefix_len order.
+ */
+ static int prefix_len_insert(
+@@ -1414,7 +1446,7 @@ int reload_tables()
+ db_key_t gw_cols[13];
+ db_key_t rule_cols[7];
+ db_key_t target_cols[4];
+- pcre *from_uri_re, *request_uri_re;
++ pcre2_code *from_uri_re, *request_uri_re;
+ struct gw_info *gws, *gw_pt_tmp;
+ struct rule_info **rules, **rule_pt_tmp;
+
+@@ -2129,11 +2161,12 @@ void add_gws_into_avps(struct gw_info *g
+ int load_gws_dummy(int lcr_id, str *ruri_user, str *from_uri, str *request_uri,
+ unsigned int *gw_indexes)
+ {
+- int i, j;
++ int i, j, rc;
+ unsigned int gw_index, now, dex;
+ struct rule_info **rules, *rule, *pl;
+ struct gw_info *gws;
+ struct target *t;
++ pcre2_match_data *pcre_md = NULL;
+ struct matched_gw_info matched_gws[MAX_NO_OF_GWS + 1];
+ struct sip_uri furi;
+ struct usr_avp *avp;
+@@ -2178,12 +2211,18 @@ int load_gws_dummy(int lcr_id, str *ruri
+ || strncmp(rule->prefix, ruri_user->s, pl->prefix_len))
+ goto next;
+
+- if((rule->from_uri_len != 0)
+- && (pcre_exec(rule->from_uri_re, NULL, from_uri->s,
+- from_uri->len, 0, 0, NULL, 0)
+- < 0))
+- goto next;
+-
++ if(rule->from_uri_len != 0) {
++ pcre_md = pcre2_match_data_create_from_pattern(
++ rule->from_uri_re, NULL);
++ rc = pcre2_match(rule->from_uri_re, (PCRE2_SPTR)from_uri->s,
++ (PCRE2_SIZE)from_uri->len, 0, 0, pcre_md, NULL);
++ if(pcre_md) {
++ pcre2_match_data_free(pcre_md);
++ pcre_md = NULL;
++ }
++ if(rc < 0)
++ goto next;
++ }
+ if((from_uri->len > 0) && (rule->mt_tvalue_len > 0)) {
+ if(mtree_api.mt_match(&msg, &mtree_param, &(furi.user), 2)
+ == -1) {
+@@ -2216,9 +2255,16 @@ int load_gws_dummy(int lcr_id, str *ruri
+ "param has not been given.\n");
+ return -1;
+ }
+- if(pcre_exec(rule->request_uri_re, NULL, request_uri->s,
+- request_uri->len, 0, 0, NULL, 0)
+- < 0)
++ pcre_md = pcre2_match_data_create_from_pattern(
++ rule->request_uri_re, NULL);
++ rc = pcre2_match(rule->request_uri_re,
++ (PCRE2_SPTR)request_uri->s,
++ (PCRE2_SIZE)request_uri->len, 0, 0, pcre_md, NULL);
++ if(pcre_md) {
++ pcre2_match_data_free(pcre_md);
++ pcre_md = NULL;
++ }
++ if(rc < 0)
+ goto next;
+ }
+
+@@ -2282,9 +2328,10 @@ static int ki_load_gws_furi(
+ sip_msg_t *_m, int lcr_id, str *ruri_user, str *from_uri)
+ {
+ str *request_uri;
+- int i, j;
++ int i, j, rc;
+ unsigned int gw_index, now, dex;
+ int_str val;
++ pcre2_match_data *pcre_md = NULL;
+ struct matched_gw_info matched_gws[MAX_NO_OF_GWS + 1];
+ struct rule_info **rules, *rule, *pl;
+ struct gw_info *gws;
+@@ -2343,14 +2390,22 @@ static int ki_load_gws_furi(
+ goto next;
+
+ /* Match from uri */
+- if((rule->from_uri_len != 0)
+- && (pcre_exec(rule->from_uri_re, NULL, from_uri->s,
+- from_uri->len, 0, 0, NULL, 0)
+- < 0)) {
+- LM_DBG("from uri <%.*s> did not match to from regex <%.*s>\n",
+- from_uri->len, from_uri->s, rule->from_uri_len,
+- rule->from_uri);
+- goto next;
++ if(rule->from_uri_len != 0) {
++ pcre_md = pcre2_match_data_create_from_pattern(
++ rule->from_uri_re, NULL);
++ rc = pcre2_match(rule->from_uri_re, (PCRE2_SPTR)from_uri->s,
++ (PCRE2_SIZE)from_uri->len, 0, 0, pcre_md, NULL);
++ if(pcre_md) {
++ pcre2_match_data_free(pcre_md);
++ pcre_md = NULL;
++ }
++ if(rc < 0) {
++ LM_DBG("from uri <%.*s> did not match to from regex "
++ "<%.*s>\n",
++ from_uri->len, from_uri->s, rule->from_uri_len,
++ rule->from_uri);
++ goto next;
++ }
+ }
+
+ /* Match from uri user */
+@@ -2379,15 +2434,23 @@ static int ki_load_gws_furi(
+ }
+
+ /* Match request uri */
+- if((rule->request_uri_len != 0)
+- && (pcre_exec(rule->request_uri_re, NULL, request_uri->s,
+- request_uri->len, 0, 0, NULL, 0)
+- < 0)) {
+- LM_DBG("request uri <%.*s> did not match to request regex "
+- "<%.*s>\n",
+- request_uri->len, request_uri->s, rule->request_uri_len,
+- rule->request_uri);
+- goto next;
++ if(rule->request_uri_len != 0) {
++ pcre_md = pcre2_match_data_create_from_pattern(
++ rule->request_uri_re, NULL);
++ rc = pcre2_match(rule->request_uri_re,
++ (PCRE2_SPTR)request_uri->s,
++ (PCRE2_SIZE)request_uri->len, 0, 0, pcre_md, NULL);
++ if(pcre_md) {
++ pcre2_match_data_free(pcre_md);
++ pcre_md = NULL;
++ }
++ if(rc < 0) {
++ LM_DBG("request uri <%.*s> did not match to request regex "
++ "<%.*s>\n",
++ request_uri->len, request_uri->s,
++ rule->request_uri_len, rule->request_uri);
++ goto next;
++ }
+ }
+
+ /* Load gws associated with this rule */
+@@ -3015,7 +3078,7 @@ static int ki_next_gw(sip_msg_t *_m)
+ }
+
+ /**
+- *
++ *
+ */
+ static int next_gw(struct sip_msg *_m, char *_s1, char *_s2)
+ {
+--- a/src/modules/lcr/lcr_mod.h
++++ b/src/modules/lcr/lcr_mod.h
+@@ -2,6 +2,7 @@
+ * Various lcr related constant, types, and external variables
+ *
+ * Copyright (C) 2005-2014 Juha Heinanen
++ * Copyright (C) 2023 Victor Seva
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+@@ -33,7 +34,8 @@
+ #define LCR_MOD_H
+
+ #include <stdio.h>
+-#include <pcre.h>
++#define PCRE2_CODE_UNIT_WIDTH 8
++#include <pcre2.h>
+ #include "../../core/locking.h"
+ #include "../../core/parser/parse_uri.h"
+ #include "../../core/ip_addr.h"
+@@ -60,10 +62,10 @@ struct rule_info
+ unsigned short from_uri_len;
+ char mt_tvalue[MAX_MT_TVALUE_LEN + 1];
+ unsigned short mt_tvalue_len;
+- pcre *from_uri_re;
++ pcre2_code *from_uri_re;
+ char request_uri[MAX_URI_LEN + 1];
+ unsigned short request_uri_len;
+- pcre *request_uri_re;
++ pcre2_code *request_uri_re;
+ unsigned short stopper;
+ unsigned int enabled;
+ struct target *targets;
--- /dev/null
+From fb7c59cafceb35628d40c727dbfa2990335b922a Mon Sep 17 00:00:00 2001
+From: Victor Seva <linuxmaniac@torreviejawireless.org>
+Date: Wed, 17 May 2023 16:37:10 +0200
+Subject: [PATCH] regex: clang-format for coherent indentation and coding style
+
+---
+ src/modules/regex/regex_mod.c | 313 ++++++++++++++++------------------
+ 1 file changed, 150 insertions(+), 163 deletions(-)
+
+--- a/src/modules/regex/regex_mod.c
++++ b/src/modules/regex/regex_mod.c
+@@ -49,9 +49,9 @@ MODULE_VERSION
+ #define START 0
+ #define RELOAD 1
+
+-#define FILE_MAX_LINE 500 /*!< Max line size in the file */
+-#define MAX_GROUPS 20 /*!< Max number of groups */
+-#define GROUP_MAX_SIZE 8192 /*!< Max size of a group */
++#define FILE_MAX_LINE 500 /*!< Max line size in the file */
++#define MAX_GROUPS 20 /*!< Max number of groups */
++#define GROUP_MAX_SIZE 8192 /*!< Max size of a group */
+
+
+ static int regex_init_rpc(void);
+@@ -66,12 +66,12 @@ gen_lock_t *reload_lock;
+ * Module exported parameter variables
+ */
+ static char *file;
+-static int max_groups = MAX_GROUPS;
+-static int group_max_size = GROUP_MAX_SIZE;
+-static int pcre_caseless = 0;
+-static int pcre_multiline = 0;
+-static int pcre_dotall = 0;
+-static int pcre_extended = 0;
++static int max_groups = MAX_GROUPS;
++static int group_max_size = GROUP_MAX_SIZE;
++static int pcre_caseless = 0;
++static int pcre_multiline = 0;
++static int pcre_dotall = 0;
++static int pcre_extended = 0;
+
+
+ /*
+@@ -100,119 +100,117 @@ static void free_shared_memory(void);
+ /*
+ * Script functions
+ */
+-static int w_pcre_match(struct sip_msg* _msg, char* _s1, char* _s2);
+-static int w_pcre_match_group(struct sip_msg* _msg, char* _s1, char* _s2);
++static int w_pcre_match(struct sip_msg *_msg, char *_s1, char *_s2);
++static int w_pcre_match_group(struct sip_msg *_msg, char *_s1, char *_s2);
+
+
+ /*
+ * Exported functions
+ */
+-static cmd_export_t cmds[] =
+-{
+- { "pcre_match", (cmd_function)w_pcre_match, 2, fixup_spve_spve, 0,
+- REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+- { "pcre_match_group", (cmd_function)w_pcre_match_group, 2, fixup_spve_spve, 0,
+- REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+- { "pcre_match_group", (cmd_function)w_pcre_match_group, 1, fixup_spve_null, 0,
+- REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
+- { 0, 0, 0, 0, 0, 0 }
+-};
++static cmd_export_t cmds[] = {
++ {"pcre_match", (cmd_function)w_pcre_match, 2, fixup_spve_spve, 0,
++ REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE
++ | LOCAL_ROUTE},
++ {"pcre_match_group", (cmd_function)w_pcre_match_group, 2,
++ fixup_spve_spve, 0,
++ REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE
++ | LOCAL_ROUTE},
++ {"pcre_match_group", (cmd_function)w_pcre_match_group, 1,
++ fixup_spve_null, 0,
++ REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE | BRANCH_ROUTE
++ | LOCAL_ROUTE},
++ {0, 0, 0, 0, 0, 0}};
+
+
+ /*
+ * Exported parameters
+ */
+-static param_export_t params[] = {
+- {"file", PARAM_STRING, &file },
+- {"max_groups", INT_PARAM, &max_groups },
+- {"group_max_size", INT_PARAM, &group_max_size },
+- {"pcre_caseless", INT_PARAM, &pcre_caseless },
+- {"pcre_multiline", INT_PARAM, &pcre_multiline },
+- {"pcre_dotall", INT_PARAM, &pcre_dotall },
+- {"pcre_extended", INT_PARAM, &pcre_extended },
+- {0, 0, 0}
+-};
++static param_export_t params[] = {{"file", PARAM_STRING, &file},
++ {"max_groups", INT_PARAM, &max_groups},
++ {"group_max_size", INT_PARAM, &group_max_size},
++ {"pcre_caseless", INT_PARAM, &pcre_caseless},
++ {"pcre_multiline", INT_PARAM, &pcre_multiline},
++ {"pcre_dotall", INT_PARAM, &pcre_dotall},
++ {"pcre_extended", INT_PARAM, &pcre_extended}, {0, 0, 0}};
+
+
+ /*
+ * Module interface
+ */
+ struct module_exports exports = {
+- "regex", /*!< module name */
+- DEFAULT_DLFLAGS, /*!< dlopen flags */
+- cmds, /*!< exported functions */
+- params, /*!< exported parameters */
+- 0, /*!< exported RPC functions */
+- 0, /*!< exported pseudo-variables */
+- 0, /*!< response handling function */
+- mod_init, /*!< module initialization function */
+- 0, /*!< per-child init function */
+- destroy /*!< destroy function */
++ "regex", /*!< module name */
++ DEFAULT_DLFLAGS, /*!< dlopen flags */
++ cmds, /*!< exported functions */
++ params, /*!< exported parameters */
++ 0, /*!< exported RPC functions */
++ 0, /*!< exported pseudo-variables */
++ 0, /*!< response handling function */
++ mod_init, /*!< module initialization function */
++ 0, /*!< per-child init function */
++ destroy /*!< destroy function */
+ };
+
+
+-
+ /*! \brief
+ * Init module function
+ */
+ static int mod_init(void)
+ {
+- if(regex_init_rpc()<0)
+- {
++ if(regex_init_rpc() < 0) {
+ LM_ERR("failed to register RPC commands\n");
+ return -1;
+ }
+
+ /* Group matching feature */
+- if (file == NULL) {
++ if(file == NULL) {
+ LM_NOTICE("'file' parameter is not set, group matching disabled\n");
+ } else {
+ /* Create and init the lock */
+ reload_lock = lock_alloc();
+- if (reload_lock == NULL) {
++ if(reload_lock == NULL) {
+ LM_ERR("cannot allocate reload_lock\n");
+ goto err;
+ }
+- if (lock_init(reload_lock) == NULL) {
++ if(lock_init(reload_lock) == NULL) {
+ LM_ERR("cannot init the reload_lock\n");
+ lock_dealloc(reload_lock);
+ goto err;
+ }
+
+ /* PCRE options */
+- if (pcre_caseless != 0) {
++ if(pcre_caseless != 0) {
+ LM_DBG("PCRE CASELESS enabled\n");
+ pcre_options = pcre_options | PCRE_CASELESS;
+ }
+- if (pcre_multiline != 0) {
++ if(pcre_multiline != 0) {
+ LM_DBG("PCRE MULTILINE enabled\n");
+ pcre_options = pcre_options | PCRE_MULTILINE;
+ }
+- if (pcre_dotall != 0) {
++ if(pcre_dotall != 0) {
+ LM_DBG("PCRE DOTALL enabled\n");
+ pcre_options = pcre_options | PCRE_DOTALL;
+ }
+- if (pcre_extended != 0) {
++ if(pcre_extended != 0) {
+ LM_DBG("PCRE EXTENDED enabled\n");
+ pcre_options = pcre_options | PCRE_EXTENDED;
+ }
+ LM_DBG("PCRE options: %i\n", pcre_options);
+
+ /* Pointer to pcres */
+- if ((pcres_addr = shm_malloc(sizeof(pcre **))) == 0) {
++ if((pcres_addr = shm_malloc(sizeof(pcre **))) == 0) {
+ LM_ERR("no memory for pcres_addr\n");
+ goto err;
+ }
+
+ /* Integer containing the number of pcres */
+- if ((num_pcres = shm_malloc(sizeof(int))) == 0) {
++ if((num_pcres = shm_malloc(sizeof(int))) == 0) {
+ LM_ERR("no memory for num_pcres\n");
+ goto err;
+ }
+
+ /* Load the pcres */
+ LM_DBG("loading pcres...\n");
+- if (load_pcres(START)) {
++ if(load_pcres(START)) {
+ LM_ERR("failed to load pcres\n");
+ goto err;
+ }
+@@ -251,21 +249,21 @@ static int load_pcres(int action)
+ /* Get the lock */
+ lock_get(reload_lock);
+
+- if (!(f = fopen(file, "r"))) {
++ if(!(f = fopen(file, "r"))) {
+ LM_ERR("could not open file '%s'\n", file);
+ goto err;
+ }
+
+ /* Array containing each pattern in the file */
+- if ((patterns = pkg_malloc(sizeof(char*) * max_groups)) == 0) {
++ if((patterns = pkg_malloc(sizeof(char *) * max_groups)) == 0) {
+ LM_ERR("no more memory for patterns\n");
+ fclose(f);
+ goto err;
+ }
+- memset(patterns, 0, sizeof(char*) * max_groups);
++ memset(patterns, 0, sizeof(char *) * max_groups);
+
+- for (i=0; i<max_groups; i++) {
+- if ((patterns[i] = pkg_malloc(sizeof(char) * group_max_size)) == 0) {
++ for(i = 0; i < max_groups; i++) {
++ if((patterns[i] = pkg_malloc(sizeof(char) * group_max_size)) == 0) {
+ LM_ERR("no more memory for patterns[%d]\n", i);
+ fclose(f);
+ goto err;
+@@ -276,26 +274,27 @@ static int load_pcres(int action)
+ /* Read the file and extract the patterns */
+ memset(line, 0, FILE_MAX_LINE);
+ i = -1;
+- while (fgets(line, FILE_MAX_LINE-4, f) != NULL) {
++ while(fgets(line, FILE_MAX_LINE - 4, f) != NULL) {
+
+ /* Ignore comments and lines starting by space, tab, CR, LF */
+- if(isspace(line[0]) || line[0]=='#') {
++ if(isspace(line[0]) || line[0] == '#') {
+ memset(line, 0, FILE_MAX_LINE);
+ continue;
+ }
+
+ /* First group */
+- if (i == -1 && line[0] != '[') {
+- LM_ERR("first group must be initialized with [0] before any regular expression\n");
++ if(i == -1 && line[0] != '[') {
++ LM_ERR("first group must be initialized with [0] before any "
++ "regular expression\n");
+ fclose(f);
+ goto err;
+ }
+
+ /* New group */
+- if (line[0] == '[') {
++ if(line[0] == '[') {
+ i++;
+ /* Check if there are more patterns than the max value */
+- if (i >= max_groups) {
++ if(i >= max_groups) {
+ LM_ERR("max patterns exceeded\n");
+ fclose(f);
+ goto err;
+@@ -309,14 +308,14 @@ static int load_pcres(int action)
+
+ llen = strlen(line);
+ /* Check if the patter size is too big (aprox) */
+- if (strlen(patterns[i]) + llen >= group_max_size - 4) {
++ if(strlen(patterns[i]) + llen >= group_max_size - 4) {
+ LM_ERR("pattern max file exceeded\n");
+ fclose(f);
+ goto err;
+ }
+
+ /* Append ')' at the end of the line */
+- if (line[llen - 1] == '\n') {
++ if(line[llen - 1] == '\n') {
+ line[llen - 1] = ')';
+ line[llen] = '\n';
+ line[llen + 1] = '\0';
+@@ -328,7 +327,7 @@ static int load_pcres(int action)
+
+ /* Append '(' at the beginning of the line */
+ llen = strlen(patterns[i]);
+- memcpy(patterns[i]+llen, "(", 1);
++ memcpy(patterns[i] + llen, "(", 1);
+ llen++;
+
+ /* Append the line to the current pattern (including the ending 0) */
+@@ -340,16 +339,16 @@ static int load_pcres(int action)
+
+ fclose(f);
+
+- if(num_pcres_tmp==0) {
++ if(num_pcres_tmp == 0) {
+ LM_ERR("no expressions in the file\n");
+ goto err;
+ }
+
+ /* Fix the patterns */
+- for (i=0; i < num_pcres_tmp; i++) {
++ for(i = 0; i < num_pcres_tmp; i++) {
+
+ /* Convert empty groups in unmatcheable regular expression ^$ */
+- if (strlen(patterns[i]) == 1) {
++ if(strlen(patterns[i]) == 1) {
+ patterns[i][0] = '^';
+ patterns[i][1] = '$';
+ patterns[i][2] = '\0';
+@@ -357,13 +356,13 @@ static int load_pcres(int action)
+ }
+
+ /* Delete possible '\n' at the end of the pattern */
+- if (patterns[i][strlen(patterns[i])-1] == '\n') {
+- patterns[i][strlen(patterns[i])-1] = '\0';
++ if(patterns[i][strlen(patterns[i]) - 1] == '\n') {
++ patterns[i][strlen(patterns[i]) - 1] = '\0';
+ }
+
+ /* Replace '\n' with '|' (except at the end of the pattern) */
+- for (j=0; j < strlen(patterns[i]); j++) {
+- if (patterns[i][j] == '\n' && j != strlen(patterns[i])-1) {
++ for(j = 0; j < strlen(patterns[i]); j++) {
++ if(patterns[i][j] == '\n' && j != strlen(patterns[i]) - 1) {
+ patterns[i][j] = '|';
+ }
+ }
+@@ -374,38 +373,38 @@ static int load_pcres(int action)
+
+ /* Log the group patterns */
+ LM_INFO("num groups = %d\n", num_pcres_tmp);
+- for (i=0; i < num_pcres_tmp; i++) {
+- LM_INFO("<group[%d]>%s</group[%d]> (size = %i)\n", i, patterns[i],
+- i, (int)strlen(patterns[i]));
++ for(i = 0; i < num_pcres_tmp; i++) {
++ LM_INFO("<group[%d]>%s</group[%d]> (size = %i)\n", i, patterns[i], i,
++ (int)strlen(patterns[i]));
+ }
+
+ /* Temporal pointer of pcres */
+- if ((pcres_tmp = pkg_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) {
++ if((pcres_tmp = pkg_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) {
+ LM_ERR("no more memory for pcres_tmp\n");
+ goto err;
+ }
+- for (i=0; i<num_pcres_tmp; i++) {
++ for(i = 0; i < num_pcres_tmp; i++) {
+ pcres_tmp[i] = NULL;
+ }
+
+ /* Compile the patters */
+- for (i=0; i<num_pcres_tmp; i++) {
++ for(i = 0; i < num_pcres_tmp; i++) {
+
+- pcre_tmp = pcre_compile(patterns[i], pcre_options, &pcre_error,
+- &pcre_erroffset, NULL);
+- if (pcre_tmp == NULL) {
++ pcre_tmp = pcre_compile(
++ patterns[i], pcre_options, &pcre_error, &pcre_erroffset, NULL);
++ if(pcre_tmp == NULL) {
+ LM_ERR("pcre_tmp compilation of '%s' failed at offset %d: %s\n",
+ patterns[i], pcre_erroffset, pcre_error);
+ goto err;
+ }
+ pcre_rc = pcre_fullinfo(pcre_tmp, NULL, PCRE_INFO_SIZE, &pcre_size);
+- if (pcre_rc) {
++ if(pcre_rc) {
+ printf("pcre_fullinfo on compiled pattern[%i] yielded error: %d\n",
+ i, pcre_rc);
+ goto err;
+ }
+
+- if ((pcres_tmp[i] = pkg_malloc(pcre_size)) == 0) {
++ if((pcres_tmp[i] = pkg_malloc(pcre_size)) == 0) {
+ LM_ERR("no more memory for pcres_tmp[%i]\n", i);
+ goto err;
+ }
+@@ -417,22 +416,22 @@ static int load_pcres(int action)
+ }
+
+ /* Copy to shared memory */
+- if (action == RELOAD) {
+- for(i=0; i<*num_pcres; i++) { /* Use the previous num_pcres value */
+- if (pcres[i]) {
++ if(action == RELOAD) {
++ for(i = 0; i < *num_pcres; i++) { /* Use the previous num_pcres value */
++ if(pcres[i]) {
+ shm_free(pcres[i]);
+ }
+ }
+ shm_free(pcres);
+ }
+- if ((pcres = shm_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) {
++ if((pcres = shm_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) {
+ LM_ERR("no more memory for pcres\n");
+ goto err;
+ }
+ memset(pcres, 0, sizeof(pcre *) * num_pcres_tmp);
+- for (i=0; i<num_pcres_tmp; i++) {
++ for(i = 0; i < num_pcres_tmp; i++) {
+ pcre_rc = pcre_fullinfo(pcres_tmp[i], NULL, PCRE_INFO_SIZE, &pcre_size);
+- if ((pcres[i] = shm_malloc(pcre_size)) == 0) {
++ if((pcres[i] = shm_malloc(pcre_size)) == 0) {
+ LM_ERR("no more memory for pcres[%i]\n", i);
+ goto err;
+ }
+@@ -442,12 +441,12 @@ static int load_pcres(int action)
+ *pcres_addr = pcres;
+
+ /* Free used memory */
+- for (i=0; i<num_pcres_tmp; i++) {
++ for(i = 0; i < num_pcres_tmp; i++) {
+ pkg_free(pcres_tmp[i]);
+ }
+ pkg_free(pcres_tmp);
+ /* Free allocated slots for unused patterns */
+- for (i = num_pcres_tmp; i < max_groups; i++) {
++ for(i = num_pcres_tmp; i < max_groups; i++) {
+ pkg_free(patterns[i]);
+ }
+ pkg_free(patterns);
+@@ -456,26 +455,26 @@ static int load_pcres(int action)
+ return 0;
+
+ err:
+- if (patterns) {
+- for(i=0; i<max_groups; i++) {
+- if (patterns[i]) {
++ if(patterns) {
++ for(i = 0; i < max_groups; i++) {
++ if(patterns[i]) {
+ pkg_free(patterns[i]);
+ }
+ }
+ pkg_free(patterns);
+ }
+- if (pcres_tmp) {
+- for (i=0; i<num_pcres_tmp; i++) {
+- if (pcres_tmp[i]) {
++ if(pcres_tmp) {
++ for(i = 0; i < num_pcres_tmp; i++) {
++ if(pcres_tmp[i]) {
+ pkg_free(pcres_tmp[i]);
+ }
+ }
+ pkg_free(pcres_tmp);
+ }
+- if (reload_lock) {
++ if(reload_lock) {
+ lock_release(reload_lock);
+ }
+- if (action == START) {
++ if(action == START) {
+ free_shared_memory();
+ }
+ return -1;
+@@ -486,9 +485,9 @@ static void free_shared_memory(void)
+ {
+ int i;
+
+- if (pcres) {
+- for(i=0; i<*num_pcres; i++) {
+- if (pcres[i]) {
++ if(pcres) {
++ for(i = 0; i < *num_pcres; i++) {
++ if(pcres[i]) {
+ shm_free(pcres[i]);
+ }
+ }
+@@ -496,21 +495,21 @@ static void free_shared_memory(void)
+ pcres = NULL;
+ }
+
+- if (num_pcres) {
++ if(num_pcres) {
+ shm_free(num_pcres);
+ num_pcres = NULL;
+ }
+
+- if (pcres_addr) {
++ if(pcres_addr) {
+ shm_free(pcres_addr);
+ pcres_addr = NULL;
+ }
+
+- if (reload_lock) {
++ if(reload_lock) {
+ lock_destroy(reload_lock);
+ lock_dealloc(reload_lock);
+ reload_lock = NULL;
+- }
++ }
+ }
+
+
+@@ -519,32 +518,32 @@ static void free_shared_memory(void)
+ */
+
+ /*! \brief Return true if the argument matches the regular expression parameter */
+-static int ki_pcre_match(sip_msg_t* msg, str* string, str* regex)
++static int ki_pcre_match(sip_msg_t *msg, str *string, str *regex)
+ {
+ pcre *pcre_re = NULL;
+ int pcre_rc;
+ const char *pcre_error;
+ int pcre_erroffset;
+
+- pcre_re = pcre_compile(regex->s, pcre_options, &pcre_error, &pcre_erroffset, NULL);
+- if (pcre_re == NULL) {
++ pcre_re = pcre_compile(
++ regex->s, pcre_options, &pcre_error, &pcre_erroffset, NULL);
++ if(pcre_re == NULL) {
+ LM_ERR("pcre_re compilation of '%s' failed at offset %d: %s\n",
+ regex->s, pcre_erroffset, pcre_error);
+ return -4;
+ }
+
+- pcre_rc = pcre_exec(
+- pcre_re, /* the compiled pattern */
+- NULL, /* no extra data - we didn't study the pattern */
+- string->s, /* the matching string */
+- (int)(string->len), /* the length of the subject */
+- 0, /* start at offset 0 in the string */
+- 0, /* default options */
+- NULL, /* output vector for substring information */
+- 0); /* number of elements in the output vector */
++ pcre_rc = pcre_exec(pcre_re, /* the compiled pattern */
++ NULL, /* no extra data - we didn't study the pattern */
++ string->s, /* the matching string */
++ (int)(string->len), /* the length of the subject */
++ 0, /* start at offset 0 in the string */
++ 0, /* default options */
++ NULL, /* output vector for substring information */
++ 0); /* number of elements in the output vector */
+
+ /* Matching failed: handle error cases */
+- if (pcre_rc < 0) {
++ if(pcre_rc < 0) {
+ switch(pcre_rc) {
+ case PCRE_ERROR_NOMATCH:
+ LM_DBG("'%s' doesn't match '%s'\n", string->s, regex->s);
+@@ -562,28 +561,26 @@ static int ki_pcre_match(sip_msg_t* msg,
+ }
+
+ /*! \brief Return true if the argument matches the regular expression parameter */
+-static int w_pcre_match(struct sip_msg* _msg, char* _s1, char* _s2)
++static int w_pcre_match(struct sip_msg *_msg, char *_s1, char *_s2)
+ {
+ str string;
+ str regex;
+
+- if (_s1 == NULL) {
++ if(_s1 == NULL) {
+ LM_ERR("bad parameters\n");
+ return -2;
+ }
+
+- if (_s2 == NULL) {
++ if(_s2 == NULL) {
+ LM_ERR("bad parameters\n");
+ return -2;
+ }
+
+- if (fixup_get_svalue(_msg, (gparam_p)_s1, &string))
+- {
++ if(fixup_get_svalue(_msg, (gparam_p)_s1, &string)) {
+ LM_ERR("cannot print the format for string\n");
+ return -3;
+ }
+- if (fixup_get_svalue(_msg, (gparam_p)_s2, ®ex))
+- {
++ if(fixup_get_svalue(_msg, (gparam_p)_s2, ®ex)) {
+ LM_ERR("cannot print the format for regex\n");
+ return -3;
+ }
+@@ -592,17 +589,17 @@ static int w_pcre_match(struct sip_msg*
+ }
+
+ /*! \brief Return true if the string argument matches the pattern group parameter */
+-static int ki_pcre_match_group(sip_msg_t* _msg, str* string, int num_pcre)
++static int ki_pcre_match_group(sip_msg_t *_msg, str *string, int num_pcre)
+ {
+ int pcre_rc;
+
+ /* Check if group matching feature is enabled */
+- if (file == NULL) {
++ if(file == NULL) {
+ LM_ERR("group matching is disabled\n");
+ return -2;
+ }
+
+- if (num_pcre >= *num_pcres) {
++ if(num_pcre >= *num_pcres) {
+ LM_ERR("invalid pcre index '%i', there are %i pcres\n", num_pcre,
+ *num_pcres);
+ return -4;
+@@ -610,20 +607,19 @@ static int ki_pcre_match_group(sip_msg_t
+
+ lock_get(reload_lock);
+
+- pcre_rc = pcre_exec(
+- (*pcres_addr)[num_pcre], /* the compiled pattern */
+- NULL, /* no extra data - we didn't study the pattern */
+- string->s, /* the matching string */
+- (int)(string->len), /* the length of the subject */
+- 0, /* start at offset 0 in the string */
+- 0, /* default options */
+- NULL, /* output vector for substring information */
+- 0); /* number of elements in the output vector */
++ pcre_rc = pcre_exec((*pcres_addr)[num_pcre], /* the compiled pattern */
++ NULL, /* no extra data - we didn't study the pattern */
++ string->s, /* the matching string */
++ (int)(string->len), /* the length of the subject */
++ 0, /* start at offset 0 in the string */
++ 0, /* default options */
++ NULL, /* output vector for substring information */
++ 0); /* number of elements in the output vector */
+
+ lock_release(reload_lock);
+
+ /* Matching failed: handle error cases */
+- if (pcre_rc < 0) {
++ if(pcre_rc < 0) {
+ switch(pcre_rc) {
+ case PCRE_ERROR_NOMATCH:
+ LM_DBG("'%s' doesn't match pcres[%i]\n", string->s, num_pcre);
+@@ -640,29 +636,27 @@ static int ki_pcre_match_group(sip_msg_t
+ }
+
+ /*! \brief Return true if the string argument matches the pattern group parameter */
+-static int w_pcre_match_group(struct sip_msg* _msg, char* _s1, char* _s2)
++static int w_pcre_match_group(struct sip_msg *_msg, char *_s1, char *_s2)
+ {
+ str string, group;
+ unsigned int num_pcre = 0;
+
+- if (_s1 == NULL) {
++ if(_s1 == NULL) {
+ LM_ERR("bad parameters\n");
+ return -3;
+ }
+
+- if (_s2 == NULL) {
++ if(_s2 == NULL) {
+ num_pcre = 0;
+ } else {
+- if (fixup_get_svalue(_msg, (gparam_p)_s2, &group))
+- {
++ if(fixup_get_svalue(_msg, (gparam_p)_s2, &group)) {
+ LM_ERR("cannot print the format for second param\n");
+ return -5;
+ }
+ str2int(&group, &num_pcre);
+ }
+
+- if (fixup_get_svalue(_msg, (gparam_p)_s1, &string))
+- {
++ if(fixup_get_svalue(_msg, (gparam_p)_s1, &string)) {
+ LM_ERR("cannot print the format for first param\n");
+ return -5;
+ }
+@@ -676,42 +670,35 @@ static int w_pcre_match_group(struct sip
+ */
+
+ /*! \brief Reload pcres by reading the file again */
+-void regex_rpc_reload(rpc_t* rpc, void* ctx)
++void regex_rpc_reload(rpc_t *rpc, void *ctx)
+ {
+ /* Check if group matching feature is enabled */
+- if (file == NULL) {
++ if(file == NULL) {
+ LM_NOTICE("'file' parameter is not set, group matching disabled\n");
+ rpc->fault(ctx, 500, "Group matching not enabled");
+ return;
+ }
+ LM_INFO("reloading pcres...\n");
+- if (load_pcres(RELOAD)) {
++ if(load_pcres(RELOAD)) {
+ LM_ERR("failed to reload pcres\n");
+ rpc->fault(ctx, 500, "Failed to reload");
+ return;
+ }
+ LM_INFO("reload success\n");
+-
+ }
+
+-static const char* regex_rpc_reload_doc[2] = {
+- "Reload regex file",
+- 0
+-};
++static const char *regex_rpc_reload_doc[2] = {"Reload regex file", 0};
+
+ rpc_export_t regex_rpc_cmds[] = {
+- {"regex.reload", regex_rpc_reload,
+- regex_rpc_reload_doc, 0},
+- {0, 0, 0, 0}
+-};
++ {"regex.reload", regex_rpc_reload, regex_rpc_reload_doc, 0},
++ {0, 0, 0, 0}};
+
+ /**
+ * register RPC commands
+ */
+ static int regex_init_rpc(void)
+ {
+- if (rpc_register_array(regex_rpc_cmds)!=0)
+- {
++ if(rpc_register_array(regex_rpc_cmds) != 0) {
+ LM_ERR("failed to register RPC commands\n");
+ return -1;
+ }
--- /dev/null
+From 650b109dbcfe2c3083e09c987bae7ca39e4a19d2 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?=
+ =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= <git-dpa@aegee.org>
+Date: Wed, 21 Jun 2023 21:34:21 +0200
+Subject: [PATCH] regex: typos
+
+---
+ src/modules/regex/regex_mod.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/src/modules/regex/regex_mod.c
++++ b/src/modules/regex/regex_mod.c
+@@ -230,7 +230,7 @@ static void destroy(void)
+ }
+
+
+-/*! \brief Convert the file content into regular expresions and store them in pcres */
++/*! \brief Convert the file content into regular expressions and store them in pcres */
+ static int load_pcres(int action)
+ {
+ int i, j;
+@@ -307,7 +307,7 @@ static int load_pcres(int action)
+ }
+
+ llen = strlen(line);
+- /* Check if the patter size is too big (aprox) */
++ /* Check if the pattern size is too big (approx) */
+ if(strlen(patterns[i]) + llen >= group_max_size - 4) {
+ LM_ERR("pattern max file exceeded\n");
+ fclose(f);
+@@ -387,7 +387,7 @@ static int load_pcres(int action)
+ pcres_tmp[i] = NULL;
+ }
+
+- /* Compile the patters */
++ /* Compile the patterns */
+ for(i = 0; i < num_pcres_tmp; i++) {
+
+ pcre_tmp = pcre_compile(
--- /dev/null
+From 5c7de00bc0826cf739577010ba7b4882e83819cc Mon Sep 17 00:00:00 2001
+From: Victor Seva <linuxmaniac@torreviejawireless.org>
+Date: Wed, 9 Aug 2023 10:52:47 +0000
+Subject: [PATCH] regex: convert to memory error logging helper
+
+---
+ src/modules/regex/regex_mod.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/src/modules/regex/regex_mod.c
++++ b/src/modules/regex/regex_mod.c
+@@ -198,13 +198,13 @@ static int mod_init(void)
+
+ /* Pointer to pcres */
+ if((pcres_addr = shm_malloc(sizeof(pcre **))) == 0) {
+- LM_ERR("no memory for pcres_addr\n");
++ SHM_MEM_ERROR;
+ goto err;
+ }
+
+ /* Integer containing the number of pcres */
+ if((num_pcres = shm_malloc(sizeof(int))) == 0) {
+- LM_ERR("no memory for num_pcres\n");
++ SHM_MEM_ERROR;
+ goto err;
+ }
+
+@@ -425,14 +425,14 @@ static int load_pcres(int action)
+ shm_free(pcres);
+ }
+ if((pcres = shm_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) {
+- LM_ERR("no more memory for pcres\n");
++ SHM_MEM_ERROR;
+ goto err;
+ }
+ memset(pcres, 0, sizeof(pcre *) * num_pcres_tmp);
+ for(i = 0; i < num_pcres_tmp; i++) {
+ pcre_rc = pcre_fullinfo(pcres_tmp[i], NULL, PCRE_INFO_SIZE, &pcre_size);
+ if((pcres[i] = shm_malloc(pcre_size)) == 0) {
+- LM_ERR("no more memory for pcres[%i]\n", i);
++ SHM_MEM_ERROR;
+ goto err;
+ }
+ memcpy(pcres[i], pcres_tmp[i], pcre_size);
--- /dev/null
+From 325c7a34fca74770a4351e00e27fcae75d57852e Mon Sep 17 00:00:00 2001
+From: Victor Seva <linuxmaniac@torreviejawireless.org>
+Date: Wed, 9 Aug 2023 10:48:41 +0000
+Subject: [PATCH] regex: migration to pcre2
+
+---
+ src/modules/regex/Makefile | 11 +-
+ src/modules/regex/regex_mod.c | 240 ++++++++++++++++++++++------------
+ 2 files changed, 158 insertions(+), 93 deletions(-)
+
+--- a/src/modules/regex/Makefile
++++ b/src/modules/regex/Makefile
+@@ -5,20 +5,15 @@ auto_gen=
+ NAME=regex.so
+
+ ifeq ($(CROSS_COMPILE),)
+-PCRE_BUILDER = $(shell \
+- if pkg-config --exists libcre; then \
+- echo 'pkg-config libpcre'; \
+- else \
+- which pcre-config; \
+- fi)
++PCRE_BUILDER = $(shell command -v pcre2-config)
+ endif
+
+ ifeq ($(PCRE_BUILDER),)
+ PCREDEFS=-I$(LOCALBASE)/include
+- PCRELIBS=-L$(LOCALBASE)/lib -lpcre
++ PCRELIBS=-L$(LOCALBASE)/lib -lpcre2-8
+ else
+ PCREDEFS = $(shell $(PCRE_BUILDER) --cflags)
+- PCRELIBS = $(shell $(PCRE_BUILDER) --libs)
++ PCRELIBS = $(shell $(PCRE_BUILDER) --libs8)
+ endif
+
+ DEFS+=$(PCREDEFS)
+--- a/src/modules/regex/regex_mod.c
++++ b/src/modules/regex/regex_mod.c
+@@ -2,6 +2,7 @@
+ * regex module - pcre operations
+ *
+ * Copyright (C) 2008 Iñaki Baz Castillo
++ * Copyright (C) 2023 Victor Seva
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+@@ -25,6 +26,7 @@
+ * \file
+ * \brief REGEX :: Perl-compatible regular expressions using PCRE library
+ * Copyright (C) 2008 Iñaki Baz Castillo
++ * Copyright (C) 2023 Victor Seva
+ * \ingroup regex
+ */
+
+@@ -32,7 +34,8 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <sys/stat.h>
+-#include <pcre.h>
++#define PCRE2_CODE_UNIT_WIDTH 8
++#include <pcre2.h>
+ #include "../../core/sr_module.h"
+ #include "../../core/dprint.h"
+ #include "../../core/pt.h"
+@@ -77,8 +80,11 @@ static int pcre_extended = 0;
+ /*
+ * Module internal parameter variables
+ */
+-static pcre **pcres;
+-static pcre ***pcres_addr;
++static pcre2_general_context *pcres_gctx = NULL;
++static pcre2_match_context *pcres_mctx = NULL;
++static pcre2_compile_context *pcres_ctx = NULL;
++static pcre2_code **pcres;
++static pcre2_code ***pcres_addr;
+ static int *num_pcres;
+ static int pcre_options = 0x00000000;
+
+@@ -151,6 +157,17 @@ struct module_exports exports = {
+ };
+
+
++static void *pcre2_malloc(size_t size, void *ext)
++{
++ return shm_malloc(size);
++}
++
++static void pcre2_free(void *ptr, void *ext)
++{
++ shm_free(ptr);
++ ptr = NULL;
++}
++
+ /*! \brief
+ * Init module function
+ */
+@@ -180,24 +197,39 @@ static int mod_init(void)
+ /* PCRE options */
+ if(pcre_caseless != 0) {
+ LM_DBG("PCRE CASELESS enabled\n");
+- pcre_options = pcre_options | PCRE_CASELESS;
++ pcre_options = pcre_options | PCRE2_CASELESS;
+ }
+ if(pcre_multiline != 0) {
+ LM_DBG("PCRE MULTILINE enabled\n");
+- pcre_options = pcre_options | PCRE_MULTILINE;
++ pcre_options = pcre_options | PCRE2_MULTILINE;
+ }
+ if(pcre_dotall != 0) {
+ LM_DBG("PCRE DOTALL enabled\n");
+- pcre_options = pcre_options | PCRE_DOTALL;
++ pcre_options = pcre_options | PCRE2_DOTALL;
+ }
+ if(pcre_extended != 0) {
+ LM_DBG("PCRE EXTENDED enabled\n");
+- pcre_options = pcre_options | PCRE_EXTENDED;
++ pcre_options = pcre_options | PCRE2_EXTENDED;
+ }
+ LM_DBG("PCRE options: %i\n", pcre_options);
+
++ if((pcres_gctx = pcre2_general_context_create(
++ pcre2_malloc, pcre2_free, NULL))
++ == NULL) {
++ LM_ERR("pcre2 general context creation failed\n");
++ return -1;
++ }
++ if((pcres_ctx = pcre2_compile_context_create(pcres_gctx)) == NULL) {
++ LM_ERR("pcre2 compile context creation failed\n");
++ return -1;
++ }
++ if((pcres_mctx = pcre2_match_context_create(pcres_gctx)) == NULL) {
++ LM_ERR("pcre2 match context creation failed\n");
++ return -1;
++ }
++
+ /* Pointer to pcres */
+- if((pcres_addr = shm_malloc(sizeof(pcre **))) == 0) {
++ if((pcres_addr = shm_malloc(sizeof(pcre2_code **))) == 0) {
+ SHM_MEM_ERROR;
+ goto err;
+ }
+@@ -227,6 +259,18 @@ err:
+ static void destroy(void)
+ {
+ free_shared_memory();
++
++ if(pcres_ctx) {
++ pcre2_compile_context_free(pcres_ctx);
++ }
++
++ if(pcres_mctx) {
++ pcre2_match_context_free(pcres_mctx);
++ }
++
++ if(pcres_gctx) {
++ pcre2_general_context_free(pcres_gctx);
++ }
+ }
+
+
+@@ -237,13 +281,11 @@ static int load_pcres(int action)
+ FILE *f;
+ char line[FILE_MAX_LINE];
+ char **patterns = NULL;
+- pcre *pcre_tmp = NULL;
+- size_t pcre_size;
+- int pcre_rc;
+- const char *pcre_error;
+- int pcre_erroffset;
++ int pcre_error_num = 0;
++ char pcre_error[128];
++ size_t pcre_erroffset;
+ int num_pcres_tmp = 0;
+- pcre **pcres_tmp = NULL;
++ pcre2_code **pcres_tmp = NULL;
+ int llen;
+
+ /* Get the lock */
+@@ -379,38 +421,34 @@ static int load_pcres(int action)
+ }
+
+ /* Temporal pointer of pcres */
+- if((pcres_tmp = pkg_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) {
++ if((pcres_tmp = pkg_malloc(sizeof(pcre2_code *) * num_pcres_tmp)) == 0) {
+ LM_ERR("no more memory for pcres_tmp\n");
+ goto err;
+ }
+- for(i = 0; i < num_pcres_tmp; i++) {
+- pcres_tmp[i] = NULL;
+- }
++ memset(pcres_tmp, 0, sizeof(pcre2_code *) * num_pcres_tmp);
+
+ /* Compile the patterns */
+ for(i = 0; i < num_pcres_tmp; i++) {
+-
+- pcre_tmp = pcre_compile(
+- patterns[i], pcre_options, &pcre_error, &pcre_erroffset, NULL);
+- if(pcre_tmp == NULL) {
+- LM_ERR("pcre_tmp compilation of '%s' failed at offset %d: %s\n",
++ pcres_tmp[i] = pcre2_compile((PCRE2_SPTR)patterns[i],
++ PCRE2_ZERO_TERMINATED, pcre_options, &pcre_error_num,
++ &pcre_erroffset, pcres_ctx);
++ if(pcres_tmp[i] == NULL) {
++ switch(pcre2_get_error_message(
++ pcre_error_num, (PCRE2_UCHAR *)pcre_error, 128)) {
++ case PCRE2_ERROR_NOMEMORY:
++ snprintf(pcre_error, 128,
++ "unknown error[%d]: pcre2 error buffer too small",
++ pcre_error_num);
++ break;
++ case PCRE2_ERROR_BADDATA:
++ snprintf(pcre_error, 128, "unknown pcre2 error[%d]",
++ pcre_error_num);
++ break;
++ }
++ LM_ERR("pcre_tmp compilation of '%s' failed at offset %zu: %s\n",
+ patterns[i], pcre_erroffset, pcre_error);
+ goto err;
+ }
+- pcre_rc = pcre_fullinfo(pcre_tmp, NULL, PCRE_INFO_SIZE, &pcre_size);
+- if(pcre_rc) {
+- printf("pcre_fullinfo on compiled pattern[%i] yielded error: %d\n",
+- i, pcre_rc);
+- goto err;
+- }
+-
+- if((pcres_tmp[i] = pkg_malloc(pcre_size)) == 0) {
+- LM_ERR("no more memory for pcres_tmp[%i]\n", i);
+- goto err;
+- }
+-
+- memcpy(pcres_tmp[i], pcre_tmp, pcre_size);
+- pcre_free(pcre_tmp);
+ pkg_free(patterns[i]);
+ patterns[i] = NULL;
+ }
+@@ -419,31 +457,15 @@ static int load_pcres(int action)
+ if(action == RELOAD) {
+ for(i = 0; i < *num_pcres; i++) { /* Use the previous num_pcres value */
+ if(pcres[i]) {
+- shm_free(pcres[i]);
++ pcre2_code_free(pcres[i]);
+ }
+ }
+ shm_free(pcres);
+ }
+- if((pcres = shm_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) {
+- SHM_MEM_ERROR;
+- goto err;
+- }
+- memset(pcres, 0, sizeof(pcre *) * num_pcres_tmp);
+- for(i = 0; i < num_pcres_tmp; i++) {
+- pcre_rc = pcre_fullinfo(pcres_tmp[i], NULL, PCRE_INFO_SIZE, &pcre_size);
+- if((pcres[i] = shm_malloc(pcre_size)) == 0) {
+- SHM_MEM_ERROR;
+- goto err;
+- }
+- memcpy(pcres[i], pcres_tmp[i], pcre_size);
+- }
+ *num_pcres = num_pcres_tmp;
++ *pcres = *pcres_tmp;
+ *pcres_addr = pcres;
+
+- /* Free used memory */
+- for(i = 0; i < num_pcres_tmp; i++) {
+- pkg_free(pcres_tmp[i]);
+- }
+ pkg_free(pcres_tmp);
+ /* Free allocated slots for unused patterns */
+ for(i = num_pcres_tmp; i < max_groups; i++) {
+@@ -466,7 +488,7 @@ err:
+ if(pcres_tmp) {
+ for(i = 0; i < num_pcres_tmp; i++) {
+ if(pcres_tmp[i]) {
+- pkg_free(pcres_tmp[i]);
++ pcre2_code_free(pcres_tmp[i]);
+ }
+ }
+ pkg_free(pcres_tmp);
+@@ -520,42 +542,73 @@ static void free_shared_memory(void)
+ /*! \brief Return true if the argument matches the regular expression parameter */
+ static int ki_pcre_match(sip_msg_t *msg, str *string, str *regex)
+ {
+- pcre *pcre_re = NULL;
++ pcre2_code *pcre_re = NULL;
++ pcre2_match_data *pcre_md = NULL;
+ int pcre_rc;
+- const char *pcre_error;
+- int pcre_erroffset;
++ int pcre_error_num = 0;
++ char pcre_error[128];
++ size_t pcre_erroffset;
+
+- pcre_re = pcre_compile(
+- regex->s, pcre_options, &pcre_error, &pcre_erroffset, NULL);
++ pcre_re = pcre2_compile((PCRE2_SPTR)regex->s, PCRE2_ZERO_TERMINATED,
++ pcre_options, &pcre_error_num, &pcre_erroffset, pcres_ctx);
+ if(pcre_re == NULL) {
+- LM_ERR("pcre_re compilation of '%s' failed at offset %d: %s\n",
++ switch(pcre2_get_error_message(
++ pcre_error_num, (PCRE2_UCHAR *)pcre_error, 128)) {
++ case PCRE2_ERROR_NOMEMORY:
++ snprintf(pcre_error, 128,
++ "unknown error[%d]: pcre2 error buffer too small",
++ pcre_error_num);
++ break;
++ case PCRE2_ERROR_BADDATA:
++ snprintf(pcre_error, 128, "unknown pcre2 error[%d]",
++ pcre_error_num);
++ break;
++ }
++ LM_ERR("pcre_re compilation of '%s' failed at offset %zu: %s\n",
+ regex->s, pcre_erroffset, pcre_error);
+ return -4;
+ }
+
+- pcre_rc = pcre_exec(pcre_re, /* the compiled pattern */
+- NULL, /* no extra data - we didn't study the pattern */
+- string->s, /* the matching string */
+- (int)(string->len), /* the length of the subject */
+- 0, /* start at offset 0 in the string */
+- 0, /* default options */
+- NULL, /* output vector for substring information */
+- 0); /* number of elements in the output vector */
++ pcre_md = pcre2_match_data_create_from_pattern(pcre_re, pcres_gctx);
++ pcre_rc = pcre2_match(pcre_re, /* the compiled pattern */
++ (PCRE2_SPTR)string->s, /* the matching string */
++ (PCRE2_SIZE)(string->len), /* the length of the subject */
++ 0, /* start at offset 0 in the string */
++ 0, /* default options */
++ pcre_md, /* the match data block */
++ pcres_mctx); /* a match context; NULL means use defaults */
+
+ /* Matching failed: handle error cases */
+ if(pcre_rc < 0) {
+ switch(pcre_rc) {
+- case PCRE_ERROR_NOMATCH:
++ case PCRE2_ERROR_NOMATCH:
+ LM_DBG("'%s' doesn't match '%s'\n", string->s, regex->s);
+ break;
+ default:
+- LM_DBG("matching error '%d'\n", pcre_rc);
++ switch(pcre2_get_error_message(
++ pcre_rc, (PCRE2_UCHAR *)pcre_error, 128)) {
++ case PCRE2_ERROR_NOMEMORY:
++ snprintf(pcre_error, 128,
++ "unknown error[%d]: pcre2 error buffer too "
++ "small",
++ pcre_rc);
++ break;
++ case PCRE2_ERROR_BADDATA:
++ snprintf(pcre_error, 128, "unknown pcre2 error[%d]",
++ pcre_rc);
++ break;
++ }
++ LM_ERR("matching error:'%s' failed[%d]\n", pcre_error, pcre_rc);
+ break;
+ }
+- pcre_free(pcre_re);
++ if(pcre_md)
++ pcre2_match_data_free(pcre_md);
++ pcre2_code_free(pcre_re);
+ return -1;
+ }
+- pcre_free(pcre_re);
++ if(pcre_md)
++ pcre2_match_data_free(pcre_md);
++ pcre2_code_free(pcre_re);
+ LM_DBG("'%s' matches '%s'\n", string->s, regex->s);
+ return 1;
+ }
+@@ -592,6 +645,8 @@ static int w_pcre_match(struct sip_msg *
+ static int ki_pcre_match_group(sip_msg_t *_msg, str *string, int num_pcre)
+ {
+ int pcre_rc;
++ pcre2_match_data *pcre_md = NULL;
++ char pcre_error[128];
+
+ /* Check if group matching feature is enabled */
+ if(file == NULL) {
+@@ -606,26 +661,41 @@ static int ki_pcre_match_group(sip_msg_t
+ }
+
+ lock_get(reload_lock);
+-
+- pcre_rc = pcre_exec((*pcres_addr)[num_pcre], /* the compiled pattern */
+- NULL, /* no extra data - we didn't study the pattern */
+- string->s, /* the matching string */
+- (int)(string->len), /* the length of the subject */
+- 0, /* start at offset 0 in the string */
+- 0, /* default options */
+- NULL, /* output vector for substring information */
+- 0); /* number of elements in the output vector */
++ pcre_md = pcre2_match_data_create_from_pattern(
++ (*pcres_addr)[num_pcre], pcres_gctx);
++ pcre_rc = pcre2_match((*pcres_addr)[num_pcre], /* the compiled pattern */
++ (PCRE2_SPTR)string->s, /* the matching string */
++ (PCRE2_SIZE)(string->len), /* the length of the subject */
++ 0, /* start at offset 0 in the string */
++ 0, /* default options */
++ pcre_md, /* the match data block */
++ pcres_mctx); /* a match context; NULL means use defaults */
+
+ lock_release(reload_lock);
++ if(pcre_md)
++ pcre2_match_data_free(pcre_md);
+
+ /* Matching failed: handle error cases */
+ if(pcre_rc < 0) {
+ switch(pcre_rc) {
+- case PCRE_ERROR_NOMATCH:
++ case PCRE2_ERROR_NOMATCH:
+ LM_DBG("'%s' doesn't match pcres[%i]\n", string->s, num_pcre);
+ break;
+ default:
+- LM_DBG("matching error '%d'\n", pcre_rc);
++ switch(pcre2_get_error_message(
++ pcre_rc, (PCRE2_UCHAR *)pcre_error, 128)) {
++ case PCRE2_ERROR_NOMEMORY:
++ snprintf(pcre_error, 128,
++ "unknown error[%d]: pcre2 error buffer too "
++ "small",
++ pcre_rc);
++ break;
++ case PCRE2_ERROR_BADDATA:
++ snprintf(pcre_error, 128, "unknown pcre2 error[%d]",
++ pcre_rc);
++ break;
++ }
++ LM_ERR("matching error:'%s' failed[%d]\n", pcre_error, pcre_rc);
+ break;
+ }
+ return -1;