changeset 892:1c13e314e5b9

Handle unfolded header lines better.
author Ben Schmidt
date Mon, 03 Feb 2014 00:08:55 +1100
parents 4dd2c703e917
children ba29170a159e
files include/do_all_the_voodoo_here.h include/gethdrline.h src/do_all_the_voodoo_here.c src/gethdrline.c src/listcontrol.c src/mlmmj-bounce.c src/mlmmj-process.c src/mlmmj-send.c src/send_digest.c
diffstat 9 files changed, 139 insertions(+), 116 deletions(-) [+]
line wrap: on
line diff
--- a/include/do_all_the_voodoo_here.h	Thu Feb 13 09:15:28 2014 +1100
+++ b/include/do_all_the_voodoo_here.h	Mon Feb 03 00:08:55 2014 +1100
@@ -26,10 +26,10 @@
 
 #include "mlmmj.h" /* For struct mailhdr and struct strlist */
 
-int findit(const char *line, const char **headers);
+int findit(const char *line, const struct strlist *headers);
 void getinfo(const char *line, struct mailhdr *readhdrs);
 int do_all_the_voodoo_here(int infd, int outfd, int hdrfd, int footfd,
-	      const char **delhdrs, struct mailhdr *readhdrs,
+	      const struct strlist *delhdrs, struct mailhdr *readhdrs,
 	      struct strlist *allhdrs, const char *subjectprefix);
 
 #endif /* DO_ALL_THE_VOODOO_HERE_H */
--- a/include/gethdrline.h	Thu Feb 13 09:15:28 2014 +1100
+++ b/include/gethdrline.h	Mon Feb 03 00:08:55 2014 +1100
@@ -24,6 +24,6 @@
 #ifndef GETHDRLINE_H
 #define GETHDRLINE_H
 
-char *gethdrline(int fd);
+char *gethdrline(int fd,char **unfolded);
 
 #endif /* GETHDRLINE_H */
--- a/src/do_all_the_voodoo_here.c	Thu Feb 13 09:15:28 2014 +1100
+++ b/src/do_all_the_voodoo_here.c	Mon Feb 03 00:08:55 2014 +1100
@@ -29,23 +29,21 @@
 #include "mygetline.h"
 #include "gethdrline.h"
 #include "strgen.h"
-#include "chomp.h"
 #include "ctrlvalue.h"
 #include "do_all_the_voodoo_here.h"
 #include "log_error.h"
 #include "wrappers.h"
 #include "memory.h"
 
-int findit(const char *line, const char **headers)
+int findit(const char *line, const struct strlist *headers)
 {
-	int i = 0;
+	int i;
 	size_t len;
 
-	while(headers[i]) {
-		len = strlen(headers[i]);
-		if(strncasecmp(line, headers[i], len) == 0)
+	for (i=0;i<headers->count;i++) {
+		len = strlen(headers->strs[i]);
+		if(strncasecmp(line, headers->strs[i], len) == 0)
 			return 1;
-		i++;
 	}
 
 	return 0;
@@ -54,80 +52,79 @@
 void getinfo(const char *line, struct mailhdr *readhdrs)
 {
 	int i = 0;
-	size_t tokenlen, linelen, valuelen;
+	size_t tokenlen, valuelen;
 
 	while(readhdrs[i].token) {
 		tokenlen = strlen(readhdrs[i].token);
-		linelen = strlen(line);
 		if(strncasecmp(line, readhdrs[i].token, tokenlen) == 0) {
 			readhdrs[i].valuecount++;
-			valuelen = linelen - tokenlen + 1;
+			valuelen = strlen(line) - tokenlen;
 			readhdrs[i].values =
 				(char **)myrealloc(readhdrs[i].values,
 				  readhdrs[i].valuecount * sizeof(char *));
 			readhdrs[i].values[readhdrs[i].valuecount - 1] =
 					(char *)mymalloc(valuelen + 1);
-			strncpy(readhdrs[i].values[readhdrs[i].valuecount - 1],
-						line+tokenlen, valuelen);
-			chomp(readhdrs[i].values[readhdrs[i].valuecount - 1]);
+			strcpy(readhdrs[i].values[readhdrs[i].valuecount - 1],
+						line+tokenlen);
 		}
 		i++;
 	}
 }
 
 int do_all_the_voodoo_here(int infd, int outfd, int hdrfd, int footfd,
-		 const char **delhdrs, struct mailhdr *readhdrs,
+		 const struct strlist *delhdrs, struct mailhdr *readhdrs,
 		 struct strlist *allhdrs, const char *prefix)
 {
-	char *hdrline, *subject, *unqp;
+	char *hdrline, *unfolded, *subject, *unqp;
 	int hdrsadded = 0;
 	int subject_present = 0;
 
 	allhdrs->count = 0;
 	allhdrs->strs = NULL;
 
-	while((hdrline = gethdrline(infd))) {
-		/* Done with headers? Then add extra if wanted*/
-		if((strncasecmp(hdrline, "mime", 4) == 0) ||
-			((strlen(hdrline) == 1) && (hdrline[0] == '\n'))){
+	for(;;) {
+		hdrline = gethdrline(infd, &unfolded);
 
-			/* add extra headers */
-			if(!hdrsadded && hdrfd >= 0) {
+		/* add extra headers before MIME* headers,
+		   or after all headers */
+		if(!hdrsadded &&
+				(hdrline == NULL ||
+				 strncasecmp(hdrline, "mime", 4) == 0)) {
+			if(hdrfd >= 0) {
 				if(dumpfd2fd(hdrfd, outfd) < 0) {
 					log_error(LOG_ARGS, "Could not "
 						"add extra headers");
 					myfree(hdrline);
+					myfree(unfolded);
 					return -1;
-				} else
+				}
+				fsync(outfd);
+			}
 					hdrsadded = 1;
 			}
 			
-			fsync(outfd);
-
-			/* end of headers, write single LF */ 
-			if(hdrline[0] == '\n') {
-				/* but first add Subject if none is present
-				 * and a prefix is defined */
-				if (prefix && !subject_present)
-				{
-					subject = concatstr(3, "Subject: ", 
-								prefix, "\n");
+		/* end of headers */ 
+		if(hdrline == NULL) {
+			/* add Subject if none is present
+			   and a prefix is defined */
+			if (prefix && !subject_present) {
+				subject = concatstr(3,"Subject: ",prefix,"\n");
 					writen(outfd, subject, strlen(subject));
 					myfree(subject);
 					subject_present = 1;
 				}
-
-				if(writen(outfd, hdrline, strlen(hdrline))
-						< 0) {
+			/* write LF */
+			if(writen(outfd, "\n", 1) < 0) {
 					myfree(hdrline);
-					log_error(LOG_ARGS,
-							"Error writing hdrs.");
+				myfree(unfolded);
+				log_error(LOG_ARGS, "Error writing hdrs.");
 					return -1;
 				}
 				myfree(hdrline);
+			myfree(unfolded);
 				break;
 			}
-		}
+
 		/* Do we want info from hdrs? Get it before it's gone */
 		if(readhdrs)
 			getinfo(hdrline, readhdrs);
@@ -135,9 +132,8 @@
 		/* Snatch a copy of the header */
 		allhdrs->count++;
 		allhdrs->strs = myrealloc(allhdrs->strs,
-					sizeof(char *) * (allhdrs->count + 1));
+					sizeof(char *) * (allhdrs->count));
 		allhdrs->strs[allhdrs->count-1] = mystrdup(hdrline);
-		allhdrs->strs[allhdrs->count] = NULL;  /* XXX why, why, why? */
 
 		/* Add Subject: prefix if wanted */
 		if(prefix) {
@@ -146,9 +142,9 @@
 				unqp = cleanquotedp(hdrline + 8);
 				if(strstr(hdrline + 8, prefix) == NULL &&
 				   strstr(unqp, prefix) == NULL) {
-					subject = concatstr(3,
+					subject = concatstr(4,
 							"Subject: ", prefix,
-							hdrline + 8);
+							hdrline + 8, "\n");
 					writen(outfd, subject,
 							strlen(subject));
 					myfree(subject);
@@ -161,14 +157,11 @@
 		}
 		
 		/* Should it be stripped? */
-		if(delhdrs) {
-			if(!findit(hdrline, delhdrs))
-				writen(outfd, hdrline, strlen(hdrline));
-		} else
-			writen(outfd, hdrline, strlen(hdrline));
-
+		if(!delhdrs || !findit(hdrline, delhdrs))
+			writen(outfd, unfolded, strlen(unfolded));
 
 		myfree(hdrline);
+		myfree(unfolded);
 	}
 
 	/* Just print the rest of the mail */
@@ -177,7 +170,7 @@
 		return -1;
 	}
 
-	/* No more, lets add the footer if one */
+	/* No more, let's add the footer if one */
 	if(footfd >= 0)
 		if(dumpfd2fd(footfd, outfd) < 0) {
 			log_error(LOG_ARGS, "Error when adding footer");
--- a/src/gethdrline.c	Thu Feb 13 09:15:28 2014 +1100
+++ b/src/gethdrline.c	Mon Feb 03 00:08:55 2014 +1100
@@ -31,52 +31,80 @@
 #include "memory.h"
 #include "wrappers.h"
 #include "log_error.h"
+#include "chomp.h"
 
 
-char *gethdrline(int fd)
+char *gethdrline(int fd, char **unfolded)
 {
-	char *line = NULL, *retstr = NULL, *oldretstr = NULL;
+	char *line = NULL, *retstr = NULL, *oldretstr = NULL, *oldunfolded = NULL;
 	char ch;
 	ssize_t n;
 	
 	retstr = mygetline(fd);
 	if (!retstr) {
+		if (unfolded != NULL)
+			*unfolded = NULL;
 		return NULL;
 	}
 
-	/* do not attempt to unfold the end-of-headers marker */
-	if (retstr[0] == '\n')
-		return retstr;
+	if (unfolded != NULL)
+		*unfolded = mystrdup(retstr);
+
+	chomp(retstr);
+
+	/* end-of-headers */
+	if (*retstr == '\0') {
+		if (unfolded != NULL) {
+			myfree(*unfolded);
+			*unfolded = NULL;
+		}
+		myfree(retstr);
+		return NULL;
+	}
 	
 	for(;;) {
-		/* look-ahead one char to determine if we need to unfold */
+		/* look ahead one char to determine if we need to fold */
 		n = readn(fd, &ch, 1);
 		if (n == 0) {  /* end of file, and therefore also headers */
 			return retstr;
 		} else if (n == -1) {  /* error */
 			log_error(LOG_ARGS, "readn() failed in gethdrline()");
+			if (unfolded != NULL) {
+				myfree(*unfolded);
+				*unfolded = NULL;
+			}
 			myfree(retstr);
 			return NULL;
 		}
 
 		if (lseek(fd, -1, SEEK_CUR) == (off_t)-1) {
 			log_error(LOG_ARGS, "lseek() failed in gethdrline()");
+			if (unfolded != NULL) {
+				myfree(*unfolded);
+				*unfolded = NULL;
+			}
 			myfree(retstr);
 			return NULL;
 		}
 
-		if ((ch != '\t') && (ch != ' '))  /* no more unfolding */
+		if ((ch != '\t') && (ch != ' '))  /* no more folding */
+			return retstr;
+
+		line = mygetline(fd);
+		if (!line)
 			return retstr;
 
-		oldretstr = retstr;
-		line = mygetline(fd);
-		if (!line) {
-			return retstr;
+		if (unfolded != NULL) {
+			oldunfolded = *unfolded;
+			*unfolded = concatstr(2, oldunfolded, line);
+			myfree(oldunfolded);
 		}
 
+		chomp(line);
+		oldretstr = retstr;
 		retstr = concatstr(2, oldretstr, line);
+		myfree(oldretstr);
 		
-		myfree(oldretstr);
 		myfree(line);
 	}
 }
--- a/src/listcontrol.c	Thu Feb 13 09:15:28 2014 +1100
+++ b/src/listcontrol.c	Mon Feb 03 00:08:55 2014 +1100
@@ -33,7 +33,6 @@
 
 #include "mlmmj.h"
 #include "listcontrol.h"
-#include "find_email_adr.h"
 #include "getlistdelim.h"
 #include "strgen.h"
 #include "prepstdreply.h"
--- a/src/mlmmj-bounce.c	Thu Feb 13 09:15:28 2014 +1100
+++ b/src/mlmmj-bounce.c	Mon Feb 03 00:08:55 2014 +1100
@@ -43,7 +43,6 @@
 #include "log_error.h"
 #include "subscriberfuncs.h"
 #include "mygetline.h"
-#include "chomp.h"
 #include "prepstdreply.h"
 #include "memory.h"
 #include "find_email_adr.h"
@@ -136,34 +135,38 @@
 		return NULL;
 	}
 
-	while((line = gethdrline(fd))) {
+	while((line = gethdrline(fd, NULL))) {
 		linedup = mystrdup(line);
 		for(i = 0; line[i]; i++)
 			linedup[i] = tolower(line[i]);
 		search = strstr(linedup, "message/delivery-status");
 		myfree(linedup);
-		if(search)
+		if(search) {
 			indsn = 1;
+			myfree(line);
+			continue;
+		}
 		if(indsn) {
-			i = strncasecmp(line, "Final-Recipient:", 16);
-			if(i == 0) {
-				find_email_adr(line, &emails);
+			/* TODO: this parsing could be greatly improved */
+			if(strncasecmp(line, "Final-Recipient:", 16)) {
+				search = strstr(line, ";");
+				if (search) {
+					find_email_adr(search+1, &emails);
 				if(emails.emailcount > 0) {
 					addr = mystrdup(emails.emaillist[0]);
 					for(i = 0; i < emails.emailcount; i++)
 						myfree(emails.emaillist[i]);
 					myfree(emails.emaillist);
-				} else {
-					addr = NULL;
+					}
 				}
 				myfree(line);
-				return addr;
+				break;
 			}
 		}
 		myfree(line);
 	}
 
-	return NULL;
+	return addr;
 }
 
 static void print_help(const char *prg)
--- a/src/mlmmj-process.c	Thu Feb 13 09:15:28 2014 +1100
+++ b/src/mlmmj-process.c	Mon Feb 03 00:08:55 2014 +1100
@@ -51,7 +51,6 @@
 #include "subscriberfuncs.h"
 #include "memory.h"
 #include "log_oper.h"
-#include "chomp.h"
 #include "unistr.h"
 
 enum action {
@@ -345,7 +344,6 @@
 		if (match != not) {
 			if (match) {
 				hdr = mystrdup(hdrs->strs[j]);
-				chomp(hdr);
 				log_oper(listdir, OPLOGFNAME, "mlmmj-process: access -"
 						" A mail from \"%s\" with header \"%s\" was %s by"
 						" rule #%d \"%s\"", from, hdr, action_strs[act],
@@ -555,15 +553,14 @@
 	}
 
 	delheaders->strs = myrealloc(delheaders->strs,
-			(delheaders->count+3) * sizeof(char *));
+			(delheaders->count+2) * sizeof(char *));
 	delheaders->strs[delheaders->count++] = mystrdup("From ");
 	delheaders->strs[delheaders->count++] = mystrdup("Return-Path:");
-	delheaders->strs[delheaders->count] = NULL;
 
 	subjectprefix = ctrlvalue(listdir, "prefix");
 
 	if(do_all_the_voodoo_here(rawmailfd, donemailfd, hdrfd, footfd,
-				(const char**)delheaders->strs, readhdrs,
+				delheaders, readhdrs,
 				&allheaders, subjectprefix) < 0) {
 		log_error(LOG_ARGS, "Error in do_all_the_voodoo_here");
 		exit(EXIT_FAILURE);
@@ -688,12 +685,11 @@
 			delheaders->count = 0;
 			delheaders->strs = NULL;
 			delheaders->strs = myrealloc(delheaders->strs,
-				(delheaders->count+3) * sizeof(char *));
+					2 * sizeof(char *));
 			delheaders->strs[delheaders->count++] =
 				mystrdup("From ");
 			delheaders->strs[delheaders->count++] =
 				mystrdup("Return-Path:");
-			delheaders->strs[delheaders->count] = NULL;
 			if((rawmailfd = open(mailfile, O_RDONLY)) < 0) {
 				log_error(LOG_ARGS, "could not open() "
 						    "input mail file");
@@ -706,11 +702,14 @@
 				exit(EXIT_FAILURE);
 			}
 			if(do_all_the_voodoo_here(rawmailfd, donemailfd, -1,
-					-1, (const char**)delheaders->strs,
+					-1, delheaders,
 					NULL, &allheaders, NULL) < 0) {
 				log_error(LOG_ARGS, "do_all_the_voodoo_here");
 				exit(EXIT_FAILURE);
 			}
+			for(i = 0; i < delheaders->count; i++)
+				myfree(delheaders->strs[i]);
+			myfree(delheaders->strs);
 			close(rawmailfd);
 			close(donemailfd);
 			unlink(mailfile);
@@ -828,7 +827,6 @@
 			log_error(LOG_ARGS, "Found To: %s",
 				toemails.emaillist[i]);
 			for(j = 0; j < alternates->count; j++) {
-				chomp(alternates->strs[j]);
 				if(strcasecmp(alternates->strs[j],
 					toemails.emaillist[i]) == 0)
 					intocc = 1;
@@ -839,7 +837,6 @@
 			log_error(LOG_ARGS, "Found Cc: %s",
 				ccemails.emaillist[i]);
 			for(j = 0; j < alternates->count; j++) {
-				chomp(alternates->strs[j]);
 				if(strcasecmp(alternates->strs[j],
 					ccemails.emaillist[i]) == 0)
 					intocc = 1;
--- a/src/mlmmj-send.c	Thu Feb 13 09:15:28 2014 +1100
+++ b/src/mlmmj-send.c	Mon Feb 03 00:08:55 2014 +1100
@@ -844,7 +844,6 @@
 	}
 
 	verp = ctrlvalue(listdir, "verp");
-	chomp(verp);
 	if(verp == NULL)
 		if(statctrl(listdir, "verp") == 1)
 			verp = mystrdup("");
@@ -993,7 +992,6 @@
 
 	if(!relayhost) {
 		relayhost = ctrlvalue(listdir, "relayhost");
-		chomp(relayhost);
 	}
 	if(!relayhost)
 		strncpy(relay, RELAYHOST, sizeof(relay));
--- a/src/send_digest.c	Thu Feb 13 09:15:28 2014 +1100
+++ b/src/send_digest.c	Mon Feb 03 00:08:55 2014 +1100
@@ -44,7 +44,6 @@
 #include "gethdrline.h"
 #include "statctrl.h"
 #include "unistr.h"
-#include "chomp.h"
 
 
 struct mail {
@@ -119,18 +118,14 @@
 		subj = NULL;
 		from = NULL;
 
-		while ((line = gethdrline(archivefd))) {
-			if (strcmp(line, "\n") == 0) {
-				myfree(line);
-				break;
+		while ((line = gethdrline(archivefd, NULL))) {
+			if (strncasecmp(line, "Subject:", 8) == 0) {
+				myfree(subj);
+				subj = unistr_header_to_utf8(line + 8);
 			}
-			if (strncasecmp(line, "Subject: ", 9) == 0) {
-				myfree(subj);
-				subj = unistr_header_to_utf8(line + 9);
-			}
-			if (strncasecmp(line, "From: ", 6) == 0) {
+			if (strncasecmp(line, "From:", 5) == 0) {
 				myfree(from);
-				from = unistr_header_to_utf8(line + 6);
+				from = unistr_header_to_utf8(line + 5);
 			}
 			myfree(line);
 		}
@@ -174,12 +169,22 @@
 			thread_idx = num_threads-1;
 		}
 
+		tmp = from;
+		for (;;) {
+			if (isspace(*tmp)) {
+				tmp++;
+				continue;
+			}
+			break;
+		}
+		/* tmp is now left-trimmed from */
+
 		threads[thread_idx].num_mails++;
 		threads[thread_idx].mails = myrealloc(threads[thread_idx].mails,
 				threads[thread_idx].num_mails*sizeof(struct mail));
 		threads[thread_idx].mails[threads[thread_idx].num_mails-1].idx = i;
 		threads[thread_idx].mails[threads[thread_idx].num_mails-1].from =
-				concatstr(5, "      ", buf, " - ", from, "\n");
+				concatstr(5, "      ", buf, " - ", tmp, "\n");
 
 		myfree(subj);
 		myfree(from);