changeset 808:8479195595af

Move list text escaping and substitution into a text-reading function. This paves the way for doing more complicated processing such as conditionals and formatting later. Also make the way digest headers are processed more consistent with how they are processed in list texts.
author Ben Schmidt
date Wed, 04 Jan 2012 04:15:20 +1100
parents 5dc52f70e76b
children 99fb6ba7a76e
files include/prepstdreply.h src/prepstdreply.c src/send_digest.c
diffstat 3 files changed, 116 insertions(+), 93 deletions(-) [+]
line wrap: on
line diff
--- a/include/prepstdreply.h	Fri Dec 30 11:29:12 2011 +1100
+++ b/include/prepstdreply.h	Wed Jan 04 04:15:20 2012 +1100
@@ -33,7 +33,9 @@
 text *open_text_file(const char *listdir, const char *filename);
 text *open_text(const char *listdir, const char *purpose, const char *action,
 		   const char *reason, const char *type, const char *compat);
-char *get_text_line(text *txt);
+char *get_processed_text_line(text *txt,
+		const char *listaddr, const char *listdelim,
+		size_t datacount, char **data, const char *listdir);
 void close_text(text *txt);
 char *prepstdreply(const char *listdir, const char *purpose, const char *action,
 		const char *reason, const char *type, const char *compat,
--- a/src/prepstdreply.c	Fri Dec 30 11:29:12 2011 +1100
+++ b/src/prepstdreply.c	Wed Jan 04 04:15:20 2012 +1100
@@ -257,8 +257,27 @@
 }
 
 
-char *get_text_line(text *txt) {
-	return mygetline(txt->fd);
+char *get_processed_text_line(text *txt,
+		const char *listaddr, const char *listdelim,
+		size_t datacount, char **data, const char *listdir)
+{
+	char *line;
+	char *tmp;
+	char *retstr;
+
+	line = mygetline(txt->fd);
+	if (line == NULL) return NULL;
+
+	chomp(line);
+
+	tmp = unistr_escaped_to_utf8(line);
+	myfree(line);
+
+	retstr = substitute(tmp, listaddr, listdelim,
+	                 datacount, data, listdir);
+	myfree(tmp);
+
+	return retstr;
 }
 
 
@@ -276,8 +295,8 @@
 	int outfd, mailfd;
 	text *txt;
 	char *listaddr, *listdelim, *tmp, *retstr = NULL;
-	char *listfqdn, *line, *utfline, *utfsub, *utfsub2;
-	char *str = NULL;
+	char *listfqdn, *line;
+	char *str;
 	char **moredata;
 	char *headers[10] = { NULL }; /* relies on NULL to flag end */
 
@@ -345,36 +364,30 @@
 	}
 
 	for(;;) {
-		line = get_text_line(txt);
+		line = get_processed_text_line(txt, listaddr, listdelim,
+				tokencount, moredata, listdir);
 		if (!line) {
 			log_error(LOG_ARGS, "No body in listtext");
 			break;
 		}
-		if (*line == '\n') {
+		if (*line == '\0') {
 			/* 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, moredata, listdir);
-			myfree(utfsub);
-			len = strlen(str);
-			str[len] = '\n';
-			if(writen(outfd, str, len+1) < 0) {
+			len = strlen(line);
+			line[len] = '\n';
+			if(writen(outfd, line, len+1) < 0) {
 				log_error(LOG_ARGS, "Could not write std mail");
-				myfree(str);
 				myfree(line);
 				myfree(retstr);
 				retstr = NULL;
 				goto freeandreturn;
 			}
-			myfree(str);
 		} else {
 			tmp = line;
 			len = 0;
@@ -400,33 +413,24 @@
 					break;
 				}
 			}
-			utfsub = unistr_escaped_to_utf8(tmp);
-			*tmp = '\0';
-			utfsub2 = substitute(utfsub, listaddr, listdelim,
-			                     tokencount, moredata, listdir);
-			myfree(utfsub);
 			if (strncasecmp(line, "Subject:", len) == 0) {
-				tmp = unistr_utf8_to_header(utfsub2);
-				myfree(utfsub2);
-				str = concatstr(2, line, tmp);
+				tmp = unistr_utf8_to_header(tmp);
+				myfree(line);
+				line = concatstr(2, "Subject:", tmp);
 				myfree(tmp);
-			} else {
-				str = concatstr(2, line, utfsub2);
-				myfree(utfsub2);
 			}
-			len = strlen(str);
-			str[len] = '\n';
-			if(writen(outfd, str, len+1) < 0) {
+			len = strlen(line);
+			line[len] = '\n';
+			if(writen(outfd, line, len+1) < 0) {
 				log_error(LOG_ARGS, "Could not write std mail");
-				myfree(str);
 				myfree(line);
 				myfree(retstr);
 				retstr = NULL;
 				goto freeandreturn;
 			}
-			myfree(str);
 		}
 		myfree(line);
+		line = NULL;
 	}
 
 	for (i=0; headers[i] != NULL; i++) {
@@ -436,7 +440,6 @@
 			log_error(LOG_ARGS, "Could not write std mail");
 			if (line)
 				myfree(line);
-			myfree(str);
 			myfree(retstr);
 			retstr = NULL;
 			goto freeandreturn;
@@ -446,7 +449,6 @@
 	/* 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(retstr);
@@ -454,17 +456,12 @@
 		goto freeandreturn;
 	}
 
-	if (line) {
-		str = concatstr(2, line, "\n");
-		myfree(line);
-	} else {
-		str = get_text_line(txt);
+	if (line == NULL) {
+		line = get_processed_text_line(txt, listaddr, listdelim,
+				tokencount, moredata, listdir);
 	}
-	while(str) {
-		utfline = unistr_escaped_to_utf8(str);
-		myfree(str);
-
-		tmp = utfline;
+	while(line) {
+		tmp = line;
 		while (*tmp && (*tmp == ' ' || *tmp == '\t')) {
 			tmp++;
 		}
@@ -490,11 +487,10 @@
 				    while (i < len &&
 				           (str = mygetline(mailfd))) {
 				        tmp = str;
-				        str = concatstr(2,utfline,str);
+				        str = concatstr(2,line,str);
 				        myfree(tmp);
 				        if(writen(outfd,str,strlen(str)) < 0) {
 				            myfree(str);
-				            myfree(utfline);
 				            log_error(LOG_ARGS, "Could not write std mail");
 					    myfree(retstr);
 					    retstr = NULL;
@@ -510,22 +506,21 @@
 			} else {
 				log_error(LOG_ARGS, "Bad $originalmail N$ substitution");
 			}
-			myfree(utfline);
 		} else {
-			str = substitute(utfline, listaddr, listdelim,
-			                 tokencount, moredata, listdir);
-			myfree(utfline);
-			if(writen(outfd, str, strlen(str)) < 0) {
+			len = strlen(line);
+			line[len] = '\n';
+			if(writen(outfd, line, len+1) < 0) {
 				myfree(str);
 				log_error(LOG_ARGS, "Could not write std mail");
 				myfree(retstr);
 				retstr = NULL;
 				goto freeandreturn;
 			}
-			myfree(str);
 		}
 
-		str = get_text_line(txt);
+		myfree(line);
+		line = get_processed_text_line(txt, listaddr, listdelim,
+				tokencount, moredata, listdir);
 	}
 
 	fsync(outfd);
--- a/src/send_digest.c	Fri Dec 30 11:29:12 2011 +1100
+++ b/src/send_digest.c	Wed Jan 04 04:15:20 2012 +1100
@@ -181,10 +181,10 @@
 		int issue, const char *addr, const char *mlmmjsend)
 {
 	int i, fd, archivefd, status, hdrfd;
+	size_t len;
 	text * txt;
 	char buf[45];
-	char *tmp, *queuename = NULL, *archivename, *subject, *line = NULL;
-	char *utfsub, *utfsub2, *utfline;
+	char *tmp, *queuename = NULL, *archivename, *subject = NULL, *line = NULL;
 	char *boundary, *listaddr, *listdelim, *listname, *listfqdn;
 	char *subst_data[10];
 	pid_t childpid, pid;
@@ -253,21 +253,60 @@
 	subst_data[8] = "digestthreads";
 	subst_data[9] = thread_list(listdir, firstindex, lastindex);
 
-	if (txt == NULL || (line = get_text_line(txt)) == NULL ||
-			(strncasecmp(line, "Subject: ", 9) != 0)) {
+	if (txt == NULL) goto fallback_subject;
 
-		utfsub = mystrdup("Digest of $listaddr$ issue $digestissue$"
-				" ($digestinterval$)");
-	} else {
+	line = get_processed_text_line(txt, listaddr, listdelim,
+			5, subst_data, listdir);
 
-		chomp(line);
-		utfsub = unistr_escaped_to_utf8(line + 9);
+	if (line == NULL) {
+		log_error(LOG_ARGS, "No content in digest listtext");
+		goto fallback_subject;
 	}
 
-	utfsub2 = substitute(utfsub, listaddr, listdelim, 5, subst_data, listdir);
-	subject = unistr_utf8_to_header(utfsub2);
-	myfree(utfsub);
-	myfree(utfsub2);
+	tmp = line;
+	len = 0;
+	while (*tmp && *tmp != ':') {
+		tmp++;
+		len++;
+	}
+	if (!*tmp) {
+		log_error(LOG_ARGS, "No subject or invalid "
+				"subject in digest listtext");
+		goto fallback_subject;
+	}
+	tmp++;
+	len++;
+	if (strncasecmp(line, "Subject:", len) == 0) {
+		tmp = unistr_utf8_to_header(tmp);
+		subject = concatstr(2, "Subject:", tmp);
+		myfree(tmp);
+		myfree(line);
+
+		/* Skip the empty line after the subject */
+		line = get_processed_text_line(txt, listaddr, listdelim,
+				5, subst_data, listdir);
+		if (line == NULL || *line != '\0') {
+			log_error(LOG_ARGS, "Too many headers "
+					"in digest listtext");
+			goto fallback_subject;
+		}
+
+		if (line != NULL) myfree(line);
+		line = NULL;
+	} else {
+		log_error(LOG_ARGS, "No subject or invalid "
+				"subject in digest listtext");
+		goto fallback_subject;
+	}
+
+fallback_subject:
+	if (subject == NULL) {
+		tmp = substitute("Digest of $listaddr$ issue $digestissue$"
+				" ($digestinterval$)", listaddr, listdelim,
+				5, subst_data, listdir);
+		subject = unistr_utf8_to_header(tmp);
+		myfree(tmp);
+	}
 
 	tmp = concatstr(10, "From: ", listname, listdelim, "help@", listfqdn,
 			   "\nMIME-Version: 1.0"
@@ -348,32 +387,19 @@
 		}
 		myfree(tmp);
 
-		if (line && (strncasecmp(line, "Subject: ", 9) == 0)) {
+		for (;;) {
+			line = get_processed_text_line(txt, listaddr, listdelim,
+					5, subst_data, listdir);
+			if (line == NULL) break;
+			len = strlen(line);
+			line[len] = '\n';
+			if(writen(fd, line, len+1) < 0) {
 			myfree(line);
-			line = get_text_line(txt);
-			if (line && (strcmp(line, "\n") == 0)) {
-				/* skip empty line after Subject: */
-				line[0] = '\0';
-			}
-		}
-
-		if (line) {
-			do {
-				utfline = unistr_escaped_to_utf8(line);
-				myfree(line);
-
-				tmp = substitute(utfline, listaddr, listdelim,
-						5, subst_data, listdir);
-				myfree(utfline);
-
-				if(writen(fd, tmp, strlen(tmp)) < 0) {
-					myfree(tmp);
 					log_error(LOG_ARGS, "Could not write"
 							" std mail");
 					break;
 				}
-				myfree(tmp);
-			} while ((line = get_text_line(txt)));
+			myfree(line);
 		}
 
 		close_text(txt);
@@ -381,7 +407,7 @@
 		close_text(txt);
 	}
 
-	myfree(line);
+	if (line != NULL) myfree(line);
 	myfree(listaddr);
 	myfree(listdelim);
 	myfree(subst_data[1]);