diff src/prepstdreply.c @ 741:b72bcb7e08a2

Arbitrary headers in listtexts, fix default Content-Transfer-Encoding: header, and document \uNNNN substitution Also, the interface to prepstdreply() has changed; there is no longer a customheaders argument, which was never used anyway, and is now essentially redundant due to this patch.
author Ben Schmidt
date Mon, 20 Sep 2010 01:44:58 +1000
parents 4a8acfd3f95f
children b00eb39643c1
line wrap: on
line diff
--- a/src/prepstdreply.c	Mon Sep 20 01:41:32 2010 +1000
+++ b/src/prepstdreply.c	Mon Sep 20 01:44:58 2010 +1000
@@ -208,12 +208,14 @@
 
 char *prepstdreply(const char *listdir, const char *filename, const char *from,
 		   const char *to, const char *replyto, size_t tokencount,
-		   char **data, char *customheaders, const char *mailname)
+		   char **data, const char *mailname)
 {
+	size_t i, len;
 	int infd, outfd;
-	char *listaddr, *listdelim, *myfrom, *tmp, *subject, *retstr = NULL;
+	char *listaddr, *listdelim, *tmp, *retstr = NULL;
 	char *listfqdn, *line, *utfline, *utfsub, *utfsub2;
-	char *myreplyto, *myto, *str = NULL, *mydate, *mymsgid;
+	char *str = NULL;
+	char *headers[10] = { NULL }; /* relies on NULL to flag end */
 
 	if ((infd = open_listtext(listdir, filename)) < 0) {
 		return NULL;
@@ -223,49 +225,6 @@
 	listdelim = getlistdelim(listdir);
 	listfqdn = genlistfqdn(listaddr);
 
-	line = mygetline(infd);
-	if(!line || (strncasecmp(line, "Subject: ", 9) != 0)) {
-		log_error(LOG_ARGS, "No Subject in '%s' listtext. Using "
-				"standard subject", filename);
-		subject = mystrdup("mlmmj administrativa");
-	} else {
-		chomp(line);
-		utfsub = unistr_escaped_to_utf8(line + 9);
-		utfsub2 = substitute(utfsub, listaddr, listdelim, tokencount,
-				     data, NULL);
-		subject = unistr_utf8_to_header(utfsub2);
-		myfree(utfsub);
-		myfree(utfsub2);
-		myfree(line);
-
-		/* skip empty line after subject */
-		line = mygetline(infd);
-		if (line && (line[0] == '\n')) {
-			myfree(line);
-			line = NULL;
-		}
-	}
-	if (line) {
-		utfline = unistr_escaped_to_utf8(line);
-		myfree(line);
-	} else {
-		utfline = NULL;
-	}
-	
-	myfrom = substitute(from, listaddr, listdelim, tokencount, data, NULL);
-	myto = substitute(to, listaddr, listdelim, tokencount, data, NULL);
-	mydate = gendatestr();
-	mymsgid = genmsgid(listfqdn);
-
-	if(replyto) {
-		myreplyto = substitute(replyto, listaddr, listdelim,
-				       tokencount, data, NULL);
-		tmp = concatstr(3, "Reply-To: ", myreplyto, "\n");
-		myfree(myreplyto);
-		myreplyto = tmp;
-	} else
-		myreplyto = NULL;
-
 	do {
 		tmp = random_str();
 		myfree(retstr);
@@ -278,48 +237,164 @@
 	
 	if(outfd < 0) {
 		log_error(LOG_ARGS, "Could not open std mail %s", retstr);
-		myfree(str);
 		myfree(listaddr);
 		myfree(listdelim);
 		myfree(listfqdn);
-		myfree(utfline);
 		return NULL;
 	}
 
-	str = concatstr(14,
-			"From: ", myfrom,
-			"\nTo: ", myto,
-			"\n", myreplyto,
-			mymsgid,
-			mydate,
-			"Subject: ", subject,
-			"\nMIME-Version: 1.0"
-			"\nContent-Type: text/plain; charset=utf-8"
-			"\nContent-Encoding: 8bit"
-			"\n", customheaders,
-			"\n", utfline);
+	tmp = substitute(from, listaddr, listdelim,
+	                 tokencount, data, NULL);
+	headers[0] = concatstr(2, "From: ", tmp);
+	myfree(tmp);
+	tmp = substitute(to, listaddr, listdelim,
+	                 tokencount, data, NULL);
+	headers[1] = concatstr(2, "To: ", tmp);
+	myfree(tmp);
+	headers[2] = genmsgid(listfqdn);
+	chomp(headers[2]);
+	headers[3] = gendatestr();
+	chomp(headers[3]);
+	headers[4] = mystrdup("Subject: mlmmj administrivia");
+	headers[5] = mystrdup("MIME-Version: 1.0");
+	headers[6] = mystrdup("Content-Type: text/plain; charset=utf-8");
+	headers[7] = mystrdup("Content-Transfer-Encoding: 8bit");
+
+	if(replyto) {
+		tmp = substitute(replyto, listaddr, listdelim,
+		                 tokencount, data, NULL);
+		headers[8] = concatstr(2, "Reply-To: ", tmp);
+		myfree(tmp);
+	}
 
-	myfree(utfline);
+	for(;;) {
+		line = mygetline(infd);
+		if (!line) {
+			log_error(LOG_ARGS, "No body in '%s' listtext",
+					filename);
+			break;
+		}
+		if (*line == '\n') {
+			/* end of headers */
+			myfree(line);
+			line = NULL;
+			break;
+		}
+		chomp(line);
+		if (*line == ' ' || *line == '\t') {
+			/* line beginning with linear whitespace is a
+			   continuation of previous header line */
+			utfsub = unistr_escaped_to_utf8(line);
+			str = substitute(utfsub, listaddr, listdelim,
+			                 tokencount, data, NULL);
+			myfree(utfsub);
+			len = strlen(str);
+			str[len] = '\n';
+			if(writen(outfd, str, len+1) < 0) {
+				log_error(LOG_ARGS, "Could not write std mail");
+				myfree(str);
+				myfree(line);
+				myfree(listaddr);
+				myfree(listdelim);
+				myfree(listfqdn);
+				return NULL;
+			}
+			myfree(str);
+		} else {
+			tmp = line;
+			len = 0;
+			while (*tmp && *tmp != ':') {
+				tmp++;
+				len++;
+			}
+			if (!*tmp) {
+				log_error(LOG_ARGS, "No headers or invalid "
+						"header in '%s' listtext",
+						filename);
+				break;
+			}
+			tmp++;
+			len++;
+			/* remove the standard header if one matches */
+			for (i=0; headers[i] != NULL; i++) {
+				if (strncasecmp(line, headers[i], len) == 0) {
+					myfree(headers[i]);
+					while (headers[i] != NULL) {
+						headers[i] = headers[i+1];
+						i++;
+					}
+					break;
+				}
+			}
+			utfsub = unistr_escaped_to_utf8(tmp);
+			*tmp = '\0';
+			utfsub2 = substitute(utfsub, listaddr, listdelim,
+			                     tokencount, data, NULL);
+			myfree(utfsub);
+			if (strncasecmp(line, "Subject:", len) == 0) {
+				tmp = unistr_utf8_to_header(utfsub2);
+				myfree(utfsub2);
+				str = concatstr(2, line, tmp);
+				myfree(tmp);
+			} else {
+				str = concatstr(2, line, utfsub2);
+				myfree(utfsub2);
+			}
+			len = strlen(str);
+			str[len] = '\n';
+			if(writen(outfd, str, len+1) < 0) {
+				log_error(LOG_ARGS, "Could not write std mail");
+				myfree(str);
+				myfree(line);
+				myfree(listaddr);
+				myfree(listdelim);
+				myfree(listfqdn);
+				return NULL;
+			}
+			myfree(str);
+		}
+		myfree(line);
+	}
 
-	if(writen(outfd, str, strlen(str)) < 0) {
+	for (i=0; headers[i] != NULL; i++) {
+		len = strlen(headers[i]);
+		headers[i][len] = '\n';
+		if(writen(outfd, headers[i], len+1) < 0) {
 		log_error(LOG_ARGS, "Could not write std mail");
+			if (line)
+				myfree(line);
 		myfree(str);
 		myfree(listaddr);
 		myfree(listdelim);
 		myfree(listfqdn);
 		return NULL;
 	}
+	}
 
+	/* end the headers */
+	if(writen(outfd, "\n", 1) < 0) {
+		log_error(LOG_ARGS, "Could not write std mail");
+		myfree(str);
+		if (line)
+			myfree(line);
+		myfree(listaddr);
+		myfree(listdelim);
+		myfree(listfqdn);
+		return NULL;
+	}
+
+	if (line) {
+		str = concatstr(2, line, "\n");
+		myfree(line);
+	} else {
+		str = mygetline(infd);
+	}
+	while(str) {
+		utfline = unistr_escaped_to_utf8(str);
 	myfree(str);
 
-	while((str = mygetline(infd))) {
-		tmp = str;
-		utfline = unistr_escaped_to_utf8(str);
-		myfree(tmp);
-
-		tmp = utfline;
 		str = substitute(utfline, listaddr, listdelim, tokencount, data, mailname);
-		myfree(tmp);
+		myfree(utfline);
 
 		if(writen(outfd, str, strlen(str)) < 0) {
 			myfree(str);
@@ -330,6 +405,7 @@
 			return NULL;
 		}
 		myfree(str);
+		str = mygetline(infd);
 	}
 	
 	fsync(outfd);