浏览代码

textops: added remove_hf_match(hname, op, expr)

- remove headers with name hname that match the body with expr
Daniel-Constantin Mierla 3 年之前
父节点
当前提交
8b24f28e99
共有 1 个文件被更改,包括 139 次插入0 次删除
  1. 139 0
      src/modules/textops/textops.c

+ 139 - 0
src/modules/textops/textops.c

@@ -146,6 +146,7 @@ static int remove_hf_pv_f(sip_msg_t* msg, char* phf, char* foo);
 static int remove_hf_idx_f(sip_msg_t* msg, char* phname, char* pidx);
 static int remove_hf_re_pv_f(sip_msg_t* msg, char* key, char* foo);
 static int remove_hf_exp_pv_f(sip_msg_t* msg, char* ematch, char* eskip);
+static int remove_hf_match_f(sip_msg_t* msg, char* phname, char* pop, char* pexp);
 static int is_present_hf_pv_f(sip_msg_t* msg, char* key, char* foo);
 static int is_present_hf_re_pv_f(sip_msg_t* msg, char* key, char* foo);
 static int is_audio_on_hold_f(struct sip_msg *msg, char *str1, char *str2 );
@@ -264,6 +265,9 @@ static cmd_export_t cmds[]={
 	{"remove_hf_exp_pv", (cmd_function)remove_hf_exp_pv_f,2,
 		fixup_spve_spve, fixup_free_spve_spve,
 		ANY_ROUTE},
+	{"remove_hf_match", (cmd_function)remove_hf_match_f, 3,
+		fixup_spve_all, fixup_free_spve_all,
+		ANY_ROUTE},
 	{"is_present_hf_pv", (cmd_function)is_present_hf_pv_f,1,
 		fixup_spve_null, fixup_free_spve_null,
 		ANY_ROUTE},
@@ -2229,6 +2233,136 @@ static int remove_hf_exp_pv_f(sip_msg_t* msg, char* pematch, char* peskip)
 	return ki_remove_hf_exp(msg, &ematch, &eskip);
 }
 
+static int ki_remove_hf_match(sip_msg_t* msg, str* hname, str *op, str *expr)
+{
+	hdr_field_t hfm = {0};
+	hdr_field_t *hfi = NULL;
+	sr_lump_t *anchor = NULL;
+	int vop = 0;
+	int vrm = 0;
+	regex_t mre;
+	regmatch_t pmatch;
+	char c;
+	int ret = -1;
+
+	memset(&mre, 0, sizeof(regex_t));
+
+	/* ensure all headers are parsed */
+	if(parse_headers(msg, HDR_EOH_F, 0)<0) {
+		LM_ERR("error parsing headers\n");
+		return -1;
+	}
+
+	parse_hname2_str(hname, &hfm);
+	if(hfm.type==HDR_ERROR_T) {
+		LM_ERR("failed to parse header name [%.*s]\n", hname->len, hname->s);
+		return -1;
+	}
+
+	LM_DBG("trying to remove hf: [%.*s] - op: [%.*s] - exp: [%.*s]\n",
+			hname->len, hname->s, op->len, op->s, expr->len, expr->s);
+
+	if(op->len==2 && strncasecmp(op->s, "eq", op->len)==0) {
+		vop = 1;
+	} else if(op->len==2 && strncasecmp(op->s, "ne", op->len)==0) {
+		vop = 2;
+	} else if(op->len==2 && strncasecmp(op->s, "in", op->len)==0) {
+		vop = 3;
+	} else if(op->len==2 && strncasecmp(op->s, "re", op->len)==0) {
+		memset(&mre, 0, sizeof(regex_t));
+		if (regcomp(&mre, expr->s, REG_EXTENDED|REG_ICASE|REG_NEWLINE)!=0) {
+			LM_ERR("failed to compile regex: [%.*s]\n", expr->len, expr->s);
+			return -1;
+		}
+		vop = 4;
+	} else {
+		LM_ERR("unknown operator [%.*s]\n", op->len, op->s);
+		return -1;
+	}
+
+	for (hfi=msg->headers; hfi; hfi=hfi->next) {
+		if (hfm.type!=HDR_OTHER_T && hfm.type!=HDR_ERROR_T) {
+			if (hfm.type!=hfi->type) {
+				continue;
+			}
+		} else {
+			if (hfi->name.len!=hname->len) {
+				continue;
+			}
+			if(strncasecmp(hfi->name.s, hname->s, hname->len)!=0) {
+				continue;
+			}
+		}
+		vrm = 0;
+		switch(vop) {
+			case 1:
+				if(expr->len==hfi->body.len
+						&& strncmp(expr->s, hfi->body.s, expr->len)==0) {
+					vrm = 1;
+				}
+				break;
+			case 2:
+				if(expr->len!=hfi->body.len
+						|| strncmp(expr->s, hfi->body.s, expr->len)!=0) {
+					vrm = 1;
+				}
+				break;
+			case 3:
+				if(str_search(&hfi->body, expr)!=NULL) {
+					vrm = 1;
+				}
+				break;
+			case 4:
+				STR_VTOZ(hfi->body.s[hfi->body.len], c);
+				if (regexec(&mre, hfi->body.s, 1, &pmatch, 0)==0) {
+					vrm = 1;
+				}
+				STR_ZTOV(hfi->body.s[hfi->body.len], c);
+				break;
+		}
+		if(vrm==1) {
+			anchor=del_lump(msg, hfi->name.s - msg->buf, hfi->len, 0);
+			if (anchor==0) {
+				LM_ERR("cannot remove hdr %.*s\n", hname->len, hname->s);
+				ret = -1;
+				goto done;
+			}
+			ret = 1;
+		}
+	}
+	if(ret==-1) {
+		ret = 2;
+	}
+
+done:
+	if(vop==4) {
+		regfree(&mre);
+	}
+	return ret;
+}
+
+static int remove_hf_match_f(sip_msg_t* msg, char* phname, char* pop, char* pexp)
+{
+	str hname = STR_NULL;
+	str op = STR_NULL;
+	str expr = STR_NULL;
+
+	if(fixup_get_svalue(msg, (gparam_t*)phname, &hname)!=0) {
+		LM_ERR("unable to get hdr name parameter\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)pop, &op)!=0) {
+		LM_ERR("unable to get op parameter\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)pexp, &expr)!=0) {
+		LM_ERR("unable to get exp parameter\n");
+		return -1;
+	}
+
+	return ki_remove_hf_match(msg, &hname, &op, &expr);
+}
+
 static int fixup_substre(void** param, int param_no)
 {
 	struct subst_expr* se;
@@ -5149,6 +5283,11 @@ static sr_kemi_t sr_kemi_textops_exports[] = {
 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
 	},
+	{ str_init("textops"), str_init("remove_hf_match"),
+		SR_KEMIP_INT, ki_remove_hf_match,
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
 	{ str_init("textops"), str_init("replace"),
 		SR_KEMIP_INT, ki_replace,
 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,