Forráskód Böngészése

textops: simplified the code for set_multipart_body()

- use formatted string instead of a sequence of allocs and memcopy
- split helper function to have a wrapper for evaluating the cfg
function params
Daniel-Constantin Mierla 7 éve
szülő
commit
043894a539
1 módosított fájl, 165 hozzáadás és 147 törlés
  1. 165 147
      src/modules/textops/textops.c

+ 165 - 147
src/modules/textops/textops.c

@@ -1883,82 +1883,66 @@ static str* generate_boundary(str *txt, str *content_type,
 	return n;
 }
 
-int set_multibody_helper(struct sip_msg* msg, char* p1, char* p2, char* p3)
+int ki_set_multibody_helper(sip_msg_t* msg, str* nbody, str* ctype,
+		str* boundary)
 {
 	struct lump *anchor;
-	char* buf = NULL;
-	int len;
-	char* value_s;
-	int value_len;
-	str body = {0,0};
-	str nb = {0,0};
-	str oc = {0,0};
-	str cd = {0,0};
-	str delimiter = {0,0};
-	str default_delimiter = {"unique-boundary-1", 17};
-	str nc = {0,0};
-	str cth = {"Content-Type: ", 14};
+	str body = STR_NULL;
+	str delimiter = STR_NULL;
+	str default_ctype = str_init("text/plain");
+	str default_delimiter = str_init("unique-boundary-1");
+	str cd = STR_NULL;
 	str* nbb = NULL;
-	unsigned int convert = 0;
 	fparam_t header;
+	int convert;
+	str oldbody = STR_NULL;
+	str newbody = STR_NULL;
+	str oldctype = STR_NULL;
+	str newctype = STR_NULL;
+#define HBUF_SIZE	128
+	char hbuf[HBUF_SIZE];
+	str hdrctype = STR_NULL;
+	str hdrclength = STR_NULL;
+
+	if(check_multipart(msg)==1) {
+		convert = -1;
+	} else {
+		convert = 1;
+	}
+
+	if(convert==-1) {
+		if(nbody==NULL || nbody->s==NULL || nbody->len==0) {
+			LM_DBG("message has already multipart body\n");
+			return 1;
+		}
+	}
+
 	header.orig = NULL;
 	header.type = FPARAM_STR;
 	header.v.str.s = "Mime-Version: 1.0\r\n";
 	header.v.str.len = 19;
 
-	if(p3==0)
-	{
+	if(nbody!=NULL && nbody->s!=NULL && nbody->len>0) {
+		newbody.s = nbody->s;
+		newbody.len = nbody->len;
+	}
+
+	if(ctype==NULL || ctype->s==NULL || ctype->len<=0) {
+		newctype.s = default_ctype.s;
+		newctype.len = default_ctype.len;
+	} else {
+		newctype.s = ctype->s;
+		newctype.len = ctype->len;
+	}
+
+	if(boundary==NULL || boundary->s==NULL || boundary->len<=0) {
 		delimiter.s = default_delimiter.s;
 		delimiter.len = default_delimiter.len;
-	}
-	else
-	{
-		if(fixup_get_svalue(msg, (gparam_p)p3, &delimiter)!=0)
-		{
-			LM_ERR("unable to get p3\n");
-			return -1;
-		}
-		if(delimiter.s==NULL || delimiter.len == 0)
-		{
-			LM_ERR("invalid boundary parameter\n");
-			return -1;
-		}
+	} else {
+		delimiter.s = boundary->s;
+		delimiter.len = boundary->len;
 	}
 	LM_DBG("delimiter<%d>:[%.*s]\n", delimiter.len, delimiter.len, delimiter.s);
-	if(p1==0 || p2==0)
-	{
-		if(check_multipart(msg)==1) {
-			LM_WARN("body is already multipart. Do nothing\n");
-			return -1;
-		}
-		convert = 1;
-	}
-	else
-	{
-		if(fixup_get_svalue(msg, (gparam_p)p1, &nb)!=0)
-		{
-			LM_ERR("unable to get p1\n");
-			return -1;
-		}
-		if(nb.s==NULL || nb.len == 0)
-		{
-			LM_ERR("invalid body parameter\n");
-			return -1;
-		}
-		if(fixup_get_svalue(msg, (gparam_p)p2, &oc)!=0)
-		{
-			LM_ERR("unable to get p2\n");
-			return -1;
-		}
-		if(oc.s==NULL || oc.len==0)
-		{
-			LM_ERR("invalid content-type parameter\n");
-			return -1;
-		}
-		if(check_multipart(msg)==1) {
-			convert = -1;
-		}
-	}
 
 	body.len = 0;
 	body.s = get_body(msg);
@@ -1972,46 +1956,43 @@ int set_multibody_helper(struct sip_msg* msg, char* p1, char* p2, char* p3)
 	del_nonshm_lump( &(msg->body_lumps) );
 	msg->body_lumps = NULL;
 
-	if(msg->content_length)
+	if(body.len > 0)
 	{
-		if(body.len > 0)
+		if(convert==1 && newbody.len==0)
 		{
-			if(body.s+body.len>msg->buf+msg->len)
+			/* need to copy of old body to re-add as a part of new body */
+			oldbody.s=pkg_malloc(sizeof(char)*body.len);
+			if (oldbody.s==0)
 			{
-				LM_ERR("invalid content length: %d\n", body.len);
+				LM_ERR("out of pkg memory\n");
 				return -1;
 			}
-			if(convert==1)
+			memcpy(oldbody.s, body.s, body.len);
+			oldbody.len = body.len;
+			if(msg->content_type!=NULL && msg->content_type->body.s!=NULL)
 			{
-				/* need to copy body */
-				nb.s=pkg_malloc(sizeof(char)*body.len);
-				if (nb.s==0)
+				oldctype.len = msg->content_type->body.len;
+				oldctype.s=pkg_malloc(sizeof(char)*oldctype.len);
+				if (oldctype.s==0)
 				{
 					LM_ERR("out of pkg memory\n");
-					return -1;
-				}
-				memcpy(nb.s, body.s, body.len);
-				nb.len = body.len;
-				if(msg->content_type!=NULL && msg->content_type->body.s!=NULL)
-				{
-					oc.len = msg->content_type->body.len;
-					oc.s=pkg_malloc(sizeof(char)*oc.len);
-					if (oc.s==0)
-					{
-						LM_ERR("out of pkg memory\n");
-						goto error;
-					}
-					memcpy(oc.s, msg->content_type->body.s, oc.len);
+					goto error;
 				}
-			}
-			if(del_lump(msg, body.s-msg->buf, body.len, 0) == 0)
-			{
-				LM_ERR("cannot delete existing body");
-				goto error;
+				memcpy(oldctype.s, msg->content_type->body.s, oldctype.len);
 			}
 		}
+		if(del_lump(msg, body.s-msg->buf, body.len, 0) == 0)
+		{
+			LM_ERR("cannot delete existing body");
+			goto error;
+		}
 	}
 
+	/* safety check to be sure there is a body to be set in the message */
+	if(newbody.len == 0 && oldbody.len==0) {
+		LM_WARN("no body to be set in the message\n");
+		goto error;
+	}
 	anchor = anchor_lump(msg, msg->unparsed-msg->buf, 0, 0);
 	if(anchor==0)
 	{
@@ -2020,7 +2001,15 @@ int set_multibody_helper(struct sip_msg* msg, char* p1, char* p2, char* p3)
 	}
 
 	/* get initial boundary */
-	nbb = generate_boundary(&nb, &oc, &cd, &delimiter, 1);
+	if(newbody.len>0) {
+		nbb = generate_boundary(&newbody, &newctype, &cd, &delimiter, 1);
+	} else {
+		if(oldctype.len==0) {
+			nbb = generate_boundary(&oldbody, &newctype, &cd, &delimiter, 1);
+		} else {
+			nbb = generate_boundary(&oldbody, &oldctype, &cd, &delimiter, 1);
+		}
+	}
 	if(nbb==NULL)
 	{
 		LM_ERR("couldn't create initial boundary\n");
@@ -2029,69 +2018,65 @@ int set_multibody_helper(struct sip_msg* msg, char* p1, char* p2, char* p3)
 
 	if(msg->content_length==0)
 	{
-		/* need to add Content-Length */
-		len = nbb->len;
-		value_s=int2str(len, &value_len);
-
-		len=CONTENT_LENGTH_LEN+value_len+CRLF_LEN;
-		buf=pkg_malloc(sizeof(char)*len);
+		/* need to add Content-Length header */
+		hdrclength.len = snprintf(hbuf, HBUF_SIZE,
+				"Content-Length: %d\r\n", nbb->len);
+		if(hdrclength.len<0 || hdrclength.len>=HBUF_SIZE) {
+			LM_ERR("failed to build new content length\n");
+			goto error;
+		}
+		hdrclength.s=pkg_malloc(sizeof(char)*(hdrclength.len+1));
 
-		if (buf==0)
-		{
+		if (hdrclength.s==0) {
 			LM_ERR("out of pkg memory\n");
 			goto error;
 		}
-
-		memcpy(buf, CONTENT_LENGTH, CONTENT_LENGTH_LEN);
-		memcpy(buf+CONTENT_LENGTH_LEN, value_s, value_len);
-		memcpy(buf+CONTENT_LENGTH_LEN+value_len, CRLF, CRLF_LEN);
-		if (insert_new_lump_after(anchor, buf, len, 0) == 0)
+		memcpy(hdrclength.s, hbuf, hdrclength.len);
+		hdrclength.s[hdrclength.len] = '\0';
+		if (insert_new_lump_after(anchor, hdrclength.s, hdrclength.len, 0) == 0)
 		{
 			LM_ERR("failed to insert content-length lump\n");
 			goto error;
 		}
-		buf = NULL;
+		hdrclength.s = NULL;
 	}
 
-	if(convert!=-1)
+	if(convert==1)
 	{
-		/* set new content type with delimiter */
-		nc.len = delimiter.len + 27;
-		nc.s = pkg_malloc(sizeof(char)*nc.len);
-		memcpy(nc.s, "multipart/mixed;boundary=\"", 26);
-		memcpy(nc.s+26, delimiter.s, delimiter.len);
-		nc.s[26+delimiter.len] = '"';
-		LM_DBG("content-type<%d>:[%.*s]\n", nc.len, nc.len, nc.s);
-		/* add content-type */
-		if(msg->content_type==NULL || msg->content_type->body.len!=nc.len
-				|| strncmp(msg->content_type->body.s, nc.s, nc.len)!=0)
-		{
-			if(msg->content_type!=NULL)
-				if(del_lump(msg, msg->content_type->name.s-msg->buf,
-							msg->content_type->len, 0) == 0)
-				{
-					LM_ERR("failed to delete content type\n");
-					goto error;
-				}
-			value_len = nc.len;
-			len = cth.len + value_len + CRLF_LEN;
-			buf = pkg_malloc(sizeof(char)*len);
-
-			if(buf==0)
-			{
-				LM_ERR("out of pkg memory\n");
-				goto error;
-			}
-			memcpy(buf, cth.s, cth.len);
-			memcpy(buf + cth.len, nc.s, value_len);
-			memcpy(buf + cth.len + value_len, CRLF, CRLF_LEN);
-			if (insert_new_lump_after(anchor, buf, len, 0) == 0)
+		/* convert to multipart body - content-type has to be updated */
+		if(msg->content_type!=NULL) {
+			if(del_lump(msg, msg->content_type->name.s-msg->buf,
+						msg->content_type->len, 0) == 0)
 			{
-				LM_ERR("failed to insert content-type lump\n");
+				LM_ERR("failed to delete content type\n");
 				goto error;
 			}
-			buf = NULL;
 		}
+		/* set new content type with delimiter */
+		hdrctype.len = snprintf(hbuf, HBUF_SIZE-1,
+			"Content-Type: multipart/mixed;boundary=\"%.*s\"\r\n",
+			delimiter.len, delimiter.s);
+		if(hdrctype.len<0 || hdrctype.len>=HBUF_SIZE) {
+			LM_ERR("failed to build new content type\n");
+			goto error;
+		}
+
+		LM_DBG("content-type<%d>:[%.*s]\n", hdrctype.len, hdrctype.len, hbuf);
+		/* add content-type */
+		hdrctype.s = pkg_malloc(hdrctype.len + 1);
+		if(hdrctype.s==NULL) {
+			LM_ERR("not enough pkg memory\n");
+			goto error;
+		}
+		memcpy(hdrctype.s, hbuf, hdrctype.len);
+		hdrctype.s[hdrctype.len] = '\0';
+		if (insert_new_lump_after(anchor, hdrctype.s, hdrctype.len, 0) == 0)
+		{
+			LM_ERR("failed to insert content-type lump\n");
+			goto error;
+		}
+		hdrctype.s = NULL;
+
 		/* add Mime-Version header */
 		if(add_hf_helper(msg, 0, 0, &header, 0, 0)<0)
 		{
@@ -2106,28 +2091,61 @@ int set_multibody_helper(struct sip_msg* msg, char* p1, char* p2, char* p3)
 		goto error;
 	}
 
+	/* set the new message body */
 	if(insert_new_lump_after(anchor, nbb->s, nbb->len, 0)==0)
 	{
 		LM_ERR("failed to insert body lump\n");
 		goto error;
 	}
-	pkg_free(nbb);
-	if(nc.s!=NULL) pkg_free(nc.s);
-	if(convert && nb.s!=NULL) pkg_free(nb.s);
-	if(convert && oc.s!=NULL) pkg_free(oc.s);
+
 	LM_DBG("set flag FL_BODY_MULTIPART\n");
 	msg->msg_flags |= FL_BODY_MULTIPART;
+
+	pkg_free(nbb);
+	if(oldbody.s!=NULL) pkg_free(oldbody.s);
+	if(oldctype.s!=NULL) pkg_free(oldctype.s);
+
 	return 1;
 
 error:
 	if(nbb!=NULL) { pkg_free(nbb->s); pkg_free(nbb); }
-	if(nc.s!=NULL) pkg_free(nc.s);
-	if(buf!=NULL) pkg_free(buf);
-	if(convert && nb.s!=NULL) pkg_free(nb.s);
-	if(convert && oc.s!=NULL) pkg_free(oc.s);
+	if(oldbody.s!=NULL) pkg_free(oldbody.s);
+	if(oldctype.s!=NULL) pkg_free(oldctype.s);
+
 	return -1;
 }
 
+int set_multibody_helper(struct sip_msg* msg, char* p1, char* p2, char* p3)
+{
+	str nbody = STR_NULL;
+	str ctype = STR_NULL;
+	str boundary = STR_NULL;
+
+	if(p1!=NULL) {
+		if(fixup_get_svalue(msg, (gparam_t*)p1, &nbody)!=0)
+		{
+			LM_ERR("unable to get new body parameter\n");
+			return -1;
+		}
+	}
+	if(p2!=NULL) {
+		if(fixup_get_svalue(msg, (gparam_t*)p2, &ctype)!=0)
+		{
+			LM_ERR("unable to get content type parameter\n");
+			return -1;
+		}
+	}
+	if(p3!=0) {
+		if(fixup_get_svalue(msg, (gparam_t*)p3, &boundary)!=0)
+		{
+			LM_ERR("unable to get boundary parameter\n");
+			return -1;
+		}
+	}
+
+	return ki_set_multibody_helper(msg, &nbody, &ctype, &boundary);
+}
+
 static int set_multibody_0(struct sip_msg* msg, char* p1, char* p2, char* p3)
 {
 	return set_multibody_helper(msg, NULL, NULL, NULL);