Răsfoiți Sursa

dialplan: fix usage of avps in replacement expression

- clone the replacement expression to shared memory before parsing it in
  order to have variables names available at runtime
- most of variables should be safe to use now in replacement
  expressions, including avps with string name. This fixes FS#153
  reported by Andrew Pogrebennyk
- variables with dynamic name have no easy way to clone at this moment,
  thus avoid using them directly. Use instead avps or script vars
  ($var(...)), copying the value from initial variable to it. Variables
  pointing to sip message attributes are safe to use.
Daniel-Constantin Mierla 14 ani în urmă
părinte
comite
ae89dc494f
3 a modificat fișierele cu 178 adăugiri și 168 ștergeri
  1. 58 58
      modules/dialplan/dialplan.c
  2. 60 62
      modules/dialplan/dp_db.c
  3. 60 48
      modules/dialplan/dp_repl.c

+ 58 - 58
modules/dialplan/dialplan.c

@@ -111,9 +111,9 @@ static mi_export_t mi_cmds[] = {
 
 static cmd_export_t cmds[]={
 	{"dp_translate",(cmd_function)dp_translate_f,	2,	dp_trans_fixup,  0,
-				ANY_ROUTE},
+		ANY_ROUTE},
 	{"dp_translate",(cmd_function)dp_translate_f,	1,	dp_trans_fixup,  0,
-				ANY_ROUTE},
+		ANY_ROUTE},
 	{0,0,0,0,0,0}
 };
 
@@ -168,10 +168,10 @@ static int mod_init(void)
 
 		attr_pvar_s.len = strlen(attr_pvar_s.s);
 		if( (pv_parse_spec(&attr_pvar_s, attr_pvar)==NULL) ||
-		((attr_pvar->type != PVT_AVP) && (attr_pvar->type!=PVT_SCRIPTVAR))) {
-				LM_ERR("invalid pvar name\n");
-				return -1;
-			}
+				((attr_pvar->type != PVT_AVP) && (attr_pvar->type!=PVT_SCRIPTVAR))) {
+			LM_ERR("invalid pvar name\n");
+			return -1;
+		}
 	}
 
 	default_par2 = (dp_param_p)shm_malloc(sizeof(dp_param_t));
@@ -228,7 +228,7 @@ static void mod_destroy(void)
 
 static int mi_child_init(void)
 {
-    return 0;
+	return 0;
 }
 
 
@@ -245,7 +245,7 @@ static int dp_get_ivalue(struct sip_msg* msg, dp_param_p dp, int *val)
 	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)) {
+			|| value.flags&(PV_VAL_NULL|PV_VAL_EMPTY) || !(value.flags&PV_VAL_INT)) {
 		LM_ERR("no AVP or SCRIPTVAR found (error in scripts)\n");
 		return -1;
 	}
@@ -261,9 +261,9 @@ static int dp_get_svalue(struct sip_msg * msg, pv_spec_t spec, str* val)
 	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)){
-			LM_ERR("no AVP or SCRIPTVAR found (error in scripts)\n");
-			return -1;
+			|| value.flags&PV_VAL_EMPTY || !(value.flags&PV_VAL_STR)){
+		LM_ERR("no AVP or SCRIPTVAR found (error in scripts)\n");
+		return -1;
 	}
 
 	*val = value.rs;
@@ -272,7 +272,7 @@ static int dp_get_svalue(struct sip_msg * msg, pv_spec_t spec, str* val)
 
 
 static int dp_update(struct sip_msg * msg, pv_spec_t * src, pv_spec_t * dest,
-		     str * repl, str * attrs)
+		str * repl, str * attrs)
 {
 	int no_change;
 	pv_value_t val;
@@ -293,7 +293,7 @@ static int dp_update(struct sip_msg * msg, pv_spec_t * src, pv_spec_t * dest,
 	}
 
 	if(is_route_type(FAILURE_ROUTE)
-				&& (dest->type==PVT_RURI || dest->type==PVT_RURI_USERNAME)) {
+			&& (dest->type==PVT_RURI || dest->type==PVT_RURI_USERNAME)) {
 		if (append_branch(msg, 0, 0, 0, Q_UNSPECIFIED, 0, 0)!=1 ){
 			LM_ERR("append_branch action failed\n");
 			return -1;
@@ -304,7 +304,7 @@ set_attr_pvar:
 
 	if(!attr_pvar)
 		return 0;
-	
+
 	val.rs = *attrs;
 	if(attr_pvar->setf(msg, &attr_pvar->pvp, (int)EQ_T, &val)<0)
 	{
@@ -350,7 +350,7 @@ static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2)
 	attrs_par = (!attr_pvar)?NULL:&attrs;
 	if (translate(msg, input, &output, idp, attrs_par)!=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",
@@ -358,26 +358,26 @@ static int dp_translate_f(struct sip_msg* msg, char* str1, char* str2)
 
 	/*set the output*/
 	if (dp_update(msg, &repl_par->v.sp[0], &repl_par->v.sp[1], 
-	&output, attrs_par) !=0){
+				&output, attrs_par) !=0){
 		LM_ERR("cannot set the output\n");
 		return -1;
 	}
 
 	return 1;
-		
+
 }
 
 #define verify_par_type(_par_no, _spec)\
 	do{\
 		if( ((_par_no == 1) \
-			&& ((_spec).type != PVT_AVP) && ((_spec).type!=PVT_SCRIPTVAR) )\
-		  ||((_par_no == 2) \
-			&& ((_spec).type != PVT_AVP) && ((_spec).type!=PVT_SCRIPTVAR) \
-		  	&& ((_spec).type!=PVT_RURI) && (_spec.type!=PVT_RURI_USERNAME))){\
-				\
+					&& ((_spec).type != PVT_AVP) && ((_spec).type!=PVT_SCRIPTVAR) )\
+				||((_par_no == 2) \
+					&& ((_spec).type != PVT_AVP) && ((_spec).type!=PVT_SCRIPTVAR) \
+					&& ((_spec).type!=PVT_RURI) && (_spec.type!=PVT_RURI_USERNAME))){\
+			\
 			LM_ERR("Unsupported Parameter TYPE\n");\
-				return E_UNSPEC;\
-			}\
+			return E_UNSPEC;\
+		}\
 	}while(0);
 
 
@@ -433,30 +433,30 @@ static int dp_trans_fixup(void ** param, int param_no){
 		}
 	} else {
 
-	    if (((s = strchr(p, '/')) != 0) && (*(s+1)=='\0'))
-		goto error;
+		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);
-	    if(pv_parse_spec( &lstr, &dp_par->v.sp[0])==NULL)
-		goto error;
+		lstr.s = p; lstr.len = strlen(p);
+		if(pv_parse_spec( &lstr, &dp_par->v.sp[0])==NULL)
+			goto error;
 
-	    if (s != 0) {
-		lstr.s = s; lstr.len = strlen(s);
-		if (pv_parse_spec( &lstr, &dp_par->v.sp[1] )==NULL)
-		    goto error;
-		verify_par_type(param_no, dp_par->v.sp[1]);
-	    } else {
-		dp_par->v.sp[1].type = PVT_NONE;
-	    }
+		if (s != 0) {
+			lstr.s = s; lstr.len = strlen(s);
+			if (pv_parse_spec( &lstr, &dp_par->v.sp[1] )==NULL)
+				goto error;
+			verify_par_type(param_no, dp_par->v.sp[1]);
+		} else {
+			dp_par->v.sp[1].type = PVT_NONE;
+		}
 
-	    dp_par->type = DP_VAL_SPEC;
+		dp_par->type = DP_VAL_SPEC;
 
 	}
-	
+
 	*param = (void *)dp_par;
 
 	return 0;
@@ -472,14 +472,14 @@ static struct mi_root * mi_reload_rules(struct mi_root *cmd_tree, void *param)
 	struct mi_root* rpl_tree= NULL;
 
 	if (dp_connect_db() < 0) {
-	    LM_ERR("failed to reload rules fron database (db connect)\n");
-	    return 0;
+		LM_ERR("failed to reload rules fron database (db connect)\n");
+		return 0;
 	}
-	    
+
 	if(dp_load_db() != 0){
-	    LM_ERR("failed to reload rules fron database (db load)\n");
-	    dp_disconnect_db();
-	    return 0;
+		LM_ERR("failed to reload rules fron database (db load)\n");
+		dp_disconnect_db();
+		return 0;
 	}
 
 	dp_disconnect_db();
@@ -487,7 +487,7 @@ static struct mi_root * mi_reload_rules(struct mi_root *cmd_tree, void *param)
 	rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
 	if (rpl_tree==0)
 		return 0;
-	
+
 	return rpl_tree;
 }
 
@@ -546,7 +546,7 @@ static struct mi_root * mi_translate(struct mi_root *cmd, void *param)
 			input.len, input.s, idp->dp_id);
 	if (translate(NULL, input, &output, idp, &attrs)!=0){
 		LM_DBG("could not translate %.*s with dpid %i\n", 
-			input.len, input.s, idp->dp_id);
+				input.len, input.s, idp->dp_id);
 		return init_mi_tree(404, "No translation", 14);
 	}
 	LM_DBG("input %.*s with dpid %i => output %.*s\n",
@@ -586,16 +586,16 @@ static const char* dialplan_rpc_reload_doc[2] = {
 static void dialplan_rpc_reload(rpc_t* rpc, void* ctx)
 {
 	if (dp_connect_db() < 0) {
-	    LM_ERR("failed to reload rules fron database (db connect)\n");
+		LM_ERR("failed to reload rules fron database (db connect)\n");
 		rpc->fault(ctx, 500, "DB Connection Error");
-	    return;
+		return;
 	}
 
 	if(dp_load_db() != 0){
-	    LM_ERR("failed to reload rules fron database (db load)\n");
-	    dp_disconnect_db();
+		LM_ERR("failed to reload rules fron database (db load)\n");
+		dp_disconnect_db();
 		rpc->fault(ctx, 500, "Dialplan Reload Failed");
-	    return;
+		return;
 	}
 
 	dp_disconnect_db();
@@ -644,7 +644,7 @@ static void dialplan_rpc_translate(rpc_t* rpc, void* ctx)
 			input.len, input.s, idp->dp_id);
 	if (translate(NULL, input, &output, idp, &attrs)!=0){
 		LM_DBG("could not translate %.*s with dpid %i\n",
-			input.len, input.s, idp->dp_id);
+				input.len, input.s, idp->dp_id);
 		rpc->fault(ctx, 500, "No translation");
 		return;
 	}
@@ -657,8 +657,8 @@ static void dialplan_rpc_translate(rpc_t* rpc, void* ctx)
 		return;
 	}
 	if(rpc->struct_add(th, "SS",
-			"Output", &output,
-			"Attributes", &attrs)<0)
+				"Output", &output,
+				"Attributes", &attrs)<0)
 	{
 		rpc->fault(ctx, 500, "Internal error creating rpc");
 		return;

+ 60 - 62
modules/dialplan/dp_db.c

@@ -102,7 +102,7 @@ int init_db_data(void)
 		return -1;
 
 	if(db_check_table_version(&dp_dbf, dp_db_handle, &dp_table_name,
-	DP_TABLE_VERSION) < 0) {
+				DP_TABLE_VERSION) < 0) {
 		LM_ERR("error during table version check.\n");
 		goto error;
 	}
@@ -116,7 +116,7 @@ int init_db_data(void)
 
 	return 0;
 error:
-	
+
 	dp_disconnect_db();
 	return -1;
 }
@@ -217,13 +217,13 @@ int dp_load_db(void)
 	}
 
 	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);
+		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){
+					DP_TABLE_COL_NO, order, 0) < 0){
 			LM_ERR("failed to query database!\n");
 			return -1;
 		}
@@ -236,8 +236,8 @@ int dp_load_db(void)
 	} 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){
-				LM_ERR("failed to query database\n");
+					DP_TABLE_COL_NO, order, &res) < 0){
+			LM_ERR("failed to query database\n");
 			return -1;
 		}
 	}
@@ -276,7 +276,7 @@ int dp_load_db(void)
 			break;
 		}
 	}  while(RES_ROW_N(res)>0);
-	
+
 
 end:
 	/*update data*/
@@ -324,21 +324,21 @@ static pcre *reg_ex_comp(const char *pattern, int *cap_cnt)
 	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);
+				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);
+				pattern, rc);
 		return (pcre *)0;
 	}
 	rc = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, cap_cnt);
 	if (rc != 0) {
 		pcre_free(re);
 		LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n",
-			pattern, rc);
+				pattern, rc);
 		return (pcre *)0;
 	}
 	result = (pcre *)shm_malloc(size);
@@ -358,7 +358,6 @@ dpl_node_t * build_rule(db_val_t * values)
 {
 	pcre *match_comp, *subst_comp;
 	struct subst_expr *repl_comp;
-	const char *error;
 	dpl_node_t * new_rule;
 	str match_exp, subst_exp, repl_exp, attrs;
 	int matchop, cap_cnt;
@@ -373,51 +372,50 @@ dpl_node_t * build_rule(db_val_t * values)
 	match_comp = subst_comp =0;
 	repl_comp = 0;
 	new_rule = 0;
-	error = NULL;
 
 	GET_STR_VALUE(match_exp, values, 3);
 	if(matchop == REGEX_OP){
-	    match_comp = reg_ex_comp(match_exp.s, &cap_cnt);
-	    if(!match_comp){
-		LM_ERR("failed to compile match expression %.*s\n",
-		       match_exp.len, match_exp.s);
-		goto err;
-	    }
+		match_comp = reg_ex_comp(match_exp.s, &cap_cnt);
+		if(!match_comp){
+			LM_ERR("failed to compile match expression %.*s\n",
+					match_exp.len, match_exp.s);
+			goto err;
+		}
 	}
-	
+
 	LM_DBG("build_rule\n");
 	GET_STR_VALUE(repl_exp, values, 6);
 	if(repl_exp.len && repl_exp.s){
-	    repl_comp = repl_exp_parse(repl_exp);
-	    if(!repl_comp){
-		LM_ERR("failed to compile replacing expression %.*s\n",
-		       repl_exp.len, repl_exp.s);
-		goto err;
-	    }
+		repl_comp = repl_exp_parse(repl_exp);
+		if(!repl_comp){
+			LM_ERR("failed to compile replacing expression %.*s\n",
+					repl_exp.len, repl_exp.s);
+			goto err;
+		}
 	}
 
 	GET_STR_VALUE(subst_exp, values, 5);
 	if(subst_exp.s && subst_exp.len){
-	    subst_comp = reg_ex_comp(subst_exp.s, &cap_cnt);
-	    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) {
-		LM_ERR("subst expression %.*s has too many sub-expressions\n",
-		       subst_exp.len, subst_exp.s);
-		goto err;
-	    }
+		subst_comp = reg_ex_comp(subst_exp.s, &cap_cnt);
+		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) {
+			LM_ERR("subst expression %.*s has too many sub-expressions\n",
+					subst_exp.len, subst_exp.s);
+			goto err;
+		}
 	}
 
 	if (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);
-	    goto err;
+			(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);
+		goto err;
 	}
 
 	new_rule = (dpl_node_t *)shm_malloc(sizeof(dpl_node_t));
@@ -477,7 +475,7 @@ int add_rule2hash(dpl_node_t * rule, int h_index)
 
 	/*search for the corresponding dpl_id*/
 	for(crt_idp = last_idp =rules_hash[h_index]; crt_idp!= NULL; 
-		last_idp = crt_idp, crt_idp = crt_idp->next)
+			last_idp = crt_idp, crt_idp = crt_idp->next)
 		if(crt_idp->dp_id == rule->dpid)
 			break;
 
@@ -496,7 +494,7 @@ int add_rule2hash(dpl_node_t * rule, int h_index)
 
 	/*search for the corresponding dpl_index*/
 	for(indexp = last_indexp =crt_idp->first_index; indexp!=NULL; 
-		last_indexp = indexp, indexp = indexp->next){
+			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))
@@ -514,7 +512,7 @@ add_index:
 	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){
 		crt_idp->first_index = new_indexp;
@@ -531,16 +529,16 @@ add_rule:
 
 	if(indexp->last_rule)
 		indexp->last_rule->next = rule;
-	
+
 	indexp->last_rule = rule;
 
 	if(new_id){
-			crt_idp->next = rules_hash[h_index];
-			rules_hash[h_index] = crt_idp;
+		crt_idp->next = rules_hash[h_index];
+		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;
 
@@ -577,7 +575,7 @@ void destroy_hash(int index)
 			shm_free(indexp);
 			indexp=0;
 			indexp = crt_idp->first_index;
-			
+
 		}
 
 		rules_hash[index] = crt_idp->next;
@@ -596,7 +594,7 @@ void destroy_rule(dpl_node_t * rule){
 		return;
 
 	LM_DBG("destroying rule with priority %i\n", 
-		rule->pr);
+			rule->pr);
 
 	if(rule->match_comp)
 		shm_free(rule->match_comp);
@@ -613,10 +611,10 @@ void destroy_rule(dpl_node_t * rule){
 
 	if(rule->subst_exp.s)
 		shm_free(rule->subst_exp.s);
-	
+
 	if(rule->repl_exp.s)
 		shm_free(rule->repl_exp.s);
-	
+
 	if(rule->attrs.s)
 		shm_free(rule->attrs.s);
 }
@@ -632,7 +630,7 @@ dpl_id_p select_dpid(int id)
 	for(idp = rules_hash[*crt_idx]; idp!=NULL; idp = idp->next)
 		if(idp->dp_id == id)
 			return idp;
-	
+
 	return NULL;
 }
 
@@ -663,11 +661,11 @@ void list_hash(int h_index)
 void list_rule(dpl_node_t * rule)
 {
 	LM_DBG("RULE %p: pr %i next %p match_exp %.*s, "
-		"subst_exp %.*s, repl_exp %.*s and attrs %.*s\n", rule,
-		rule->pr, rule->next,
-		rule->match_exp.len, rule->match_exp.s, 
-		rule->subst_exp.len, rule->subst_exp.s,
-		rule->repl_exp.len, rule->repl_exp.s,
-		rule->attrs.len,	rule->attrs.s);
-	
+			"subst_exp %.*s, repl_exp %.*s and attrs %.*s\n", rule,
+			rule->pr, rule->next,
+			rule->match_exp.len, rule->match_exp.s, 
+			rule->subst_exp.len, rule->subst_exp.s,
+			rule->repl_exp.len, rule->repl_exp.s,
+			rule->attrs.len,	rule->attrs.s);
+
 }

+ 60 - 48
modules/dialplan/dp_repl.c

@@ -41,7 +41,7 @@
 
 void repl_expr_free(struct subst_expr *se)
 {
-    if(!se)
+	if(!se)
 		return;
 
 	if(se->replacement.s){
@@ -62,11 +62,22 @@ struct subst_expr* repl_exp_parse(str subst)
 	int replace_all;
 	char * p, *end, *repl, *repl_end;
 	int max_pmatch, r;
+	str shms;
 
 	se = 0;
 	replace_all = 0;
-	p = subst.s;
-	end = p + subst.len;
+	shms.s = NULL;
+
+	if (!(shms.s=shm_malloc((subst.len+1) * sizeof(char))) ){
+		LM_ERR("out of shm memory\n");
+		goto error;
+	}
+	memcpy(shms.s, subst.s, subst.len);
+	shms.len = subst.len;
+	shms.s[shms.len] = '\0';
+
+	p = shms.s;
+	end = p + shms.len;
 	rw_no = 0;
 
 	repl = p;
@@ -75,7 +86,7 @@ struct subst_expr* repl_exp_parse(str subst)
 
 	repl_end=p;
 
-    /* construct the subst_expr structure */
+	/* construct the subst_expr structure */
 	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 */
@@ -85,26 +96,27 @@ struct subst_expr* repl_exp_parse(str subst)
 	}
 	memset((void*)se, 0, sizeof(struct subst_expr));
 
+	se->replacement.s = shms.s;
+	shms.s = NULL;
 	se->replacement.len=repl_end-repl;
-	if (!(se->replacement.s=shm_malloc(se->replacement.len * sizeof(char))) ){
-		LM_ERR("out of shm memory \n");
-		goto error;
-	}
 	if(!rw_no){
 		replace_all = 1;
 	}
 	/* start copying */
-	memcpy(se->replacement.s, repl, se->replacement.len);
+	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;
 
-    /*replace_with is a simple structure, no shm alloc needed*/
+	/*replace_with is a simple structure, no shm alloc needed*/
 	for (r=0; r<rw_no; r++) se->replace[r]=rw[r];
 	return se;
 
 error:
+	if(shms.s != NULL)
+		shm_free(shms.s);
 	if (se) { repl_expr_free(se);}
 	return NULL;
 }
@@ -113,7 +125,7 @@ error:
 #define MAX_PHONE_NB_DIGITS		127
 static char dp_output_buf[MAX_PHONE_NB_DIGITS+1];
 int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
-		   str * result)
+		str * result)
 {
 	int repl_nb, offset, match_nb, rc, cap_cnt;
 	struct replace_with token;
@@ -144,23 +156,23 @@ int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
 				&cap_cnt);
 		if (rc != 0) {
 			LM_ERR("pcre_fullinfo on compiled pattern yielded error: %d\n",
-				rc);
+					rc);
 			return -1;;
 		}
 		if(repl_comp->max_pmatch > cap_cnt){
 			LM_ERR("illegal access to the %i-th subexpr of the subst expr\n",
-				repl_comp->max_pmatch);
+					repl_comp->max_pmatch);
 			return -1;
 		}
 
 		/*search for the pattern from the compiled subst_exp*/
 		if (pcre_exec(rule->subst_comp, NULL, string.s, string.len,
-				0, 0, ovector, 3 * (MAX_REPLACE_WITH + 1)) <= 0) {
+					0, 0, ovector, 3 * (MAX_REPLACE_WITH + 1)) <= 0) {
 			LM_ERR("the string %.*s matched "
-				"the match_exp %.*s but not the subst_exp %.*s!\n", 
-				string.len, string.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", 
+					string.len, string.s, 
+					rule->match_exp.len, rule->match_exp.s,
+					rule->subst_exp.len, rule->subst_exp.s);
 			return -1;
 		}
 	}
@@ -187,10 +199,10 @@ int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
 	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)){
+					(result->len + token.offset -offset >= MAX_PHONE_NB_DIGITS)){
 				LM_ERR("invalid length\n");
 				goto error;
 			}
@@ -198,7 +210,7 @@ int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
 			size = token.offset - offset;
 			memcpy(result->s + result->len, p + offset, size);
 			LM_DBG("copying <%.*s> from replacing string\n",
-			       size, p + offset);
+					size, p + offset);
 			result->len += size;
 			offset = token.offset;
 		}
@@ -216,10 +228,10 @@ int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
 
 				memcpy(result->s + result->len, match.s, match.len);
 				LM_DBG("copying match <%.*s> token size %d\n",
-				       match.len, match.s, token.size);
+						match.len, match.s, token.size);
 				result->len += match.len;
 				offset += token.size;
-			break;
+				break;
 			case REPLACE_CHAR:
 				if(result->len + 1>= MAX_PHONE_NB_DIGITS){
 					LM_ERR("overflow\n");
@@ -227,14 +239,14 @@ int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
 				}
 				*(result->s + result->len) = token.u.c;
 				LM_DBG("copying char <%c> token size %d\n",
-					token.u.c, token.size);
+						token.u.c, token.size);
 				result->len++;
 				offset += token.size;
-			break;
+				break;
 			case REPLACE_URI:	
 				if ( msg== NULL || msg->first_line.type!=SIP_REQUEST){
 					LM_CRIT("uri substitution attempt on no request"
-						" message\n");
+							" message\n");
 					break; /* ignore, we can continue */
 				}
 				uri= (msg->new_uri.s)?(&msg->new_uri):
@@ -245,10 +257,10 @@ int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
 				}
 				memcpy(result->s + result->len, uri->s, uri->len);
 				LM_DBG("copying uri <%.*s> token size %d\n",
-					uri->len, uri->s, token.size);
+						uri->len, uri->s, token.size);
 				result->len+=uri->len;
 				offset += token.size;
-			break;
+				break;
 			case REPLACE_SPEC:
 				if (msg== NULL) {
 					LM_DBG("replace spec attempted on no message\n");
@@ -263,12 +275,12 @@ int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
 					goto error;
 				}
 				memcpy(result->s + result->len, sv.rs.s,
-				       sv.rs.len);
+						sv.rs.len);
 				LM_DBG("copying pvar value <%.*s> token size %d\n",
-					sv.rs.len, sv.rs.s, token.size);
+						sv.rs.len, sv.rs.s, token.size);
 				result->len+=sv.rs.len;
 				offset += token.size;
-			break;
+				break;
 			default:
 				LM_CRIT("unknown type %d\n", repl_comp->replace[repl_nb].type);
 				/* ignore it */
@@ -281,7 +293,7 @@ int rule_translate(struct sip_msg *msg, str string, dpl_node_t * rule,
 		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);
+				size, p + offset);
 		result->len += size;
 	}
 
@@ -297,12 +309,12 @@ error:
 #define DP_MAX_ATTRS_LEN	32
 static char dp_attrs_buf[DP_MAX_ATTRS_LEN+1];
 int translate(struct sip_msg *msg, str input, str *output, dpl_id_p idp,
-	      str *attrs)
+		str *attrs)
 {
 	dpl_node_p rulep;
 	dpl_index_p indexp;
 	int user_len, rez;
-	
+
 	if(!input.s || !input.len) {
 		LM_ERR("invalid input string\n");
 		return -1;
@@ -323,21 +335,21 @@ search_rule:
 		switch(rulep->matchop) {
 
 			case REGEX_OP:
-			    LM_DBG("regex operator testing\n");
+				LM_DBG("regex operator testing\n");
 				rez = pcre_exec(rulep->match_comp, NULL, input.s, input.len,
-				    0, 0, NULL, 0);
-		    break;
+						0, 0, NULL, 0);
+				break;
 
 			case EQUAL_OP:
 				LM_DBG("equal operator testing\n");
-			    if(rulep->match_exp.len != input.len) {
+				if(rulep->match_exp.len != input.len) {
 					rez = -1;
 				} else {
 					rez = strncmp(rulep->match_exp.s,input.s,input.len);
 					rez = (rez==0)?0:-1;
 				}
-			break;
-	    
+				break;
+
 			default:
 				LM_ERR("bogus match operator code %i\n", rulep->matchop);
 				return -1;
@@ -351,33 +363,33 @@ search_rule:
 			if(!indexp->len)
 				break;
 		if(indexp)
-		    goto search_rule;
+			goto search_rule;
 	}
-	
-    LM_DBG("no matching rule\n");
-    return -1;
+
+	LM_DBG("no matching rule\n");
+	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);
+			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);
+					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));
 			attrs->len = rulep->attrs.len;
 			attrs->s[attrs->len] = '\0';
 
 			LM_DBG("the copied attributes are: %.*s\n",
-				attrs->len, attrs->s);
+					attrs->len, attrs->s);
 		}
 	}