shithub: Nail

Download patch

ref: a6466b6c6888d1e56795eb9ae87afb5db136dea7
parent: 88d2711854dfdf65900d9001bf7ee9c78f46ee6a
author: Ori Bernstein <[email protected]>
date: Tue Nov 3 23:32:40 EST 2020

handle multipart messages

--- a/mbox.c
+++ b/mbox.c
@@ -780,5 +780,4 @@
 	threadcreate(mbmain, nil, Stack);
 	proccreate(plumbsee, nil, Stack);
 	proccreate(plumbshow, nil, Stack);
-//	threadexitsall(nil);
 }
--- a/mesg.c
+++ b/mesg.c
@@ -128,22 +128,58 @@
 	return m;
 }
 
-static int
-mesgshow(Mesg *m)
+static Mesg*
+readparts(Mesg *m)
 {
-	int rfd, wfd;
-	char *buf, *path;
+	char *dpath, *apath;
+	int n, i, dfd;
+	Mesg *a, *best;
+	Dir *d;
+
+	dpath = estrjoin(mbox.path, m->name, nil);
+	dfd = open(dpath, OREAD);
+	free(dpath);
+	if(dfd == -1)
+		return m;
+
+	n = dirreadall(dfd, &d);
+	close(dfd);
+	if(n == -1)
+		sysfatal("%s read: %r", mbox.path);
+
+	best = nil;
+	m->attachments = emalloc(n*sizeof(Mesg*));
+	m->nattachments = 0;
+	for(i = 0; i < n; i++){
+		if(d[i].qid.type != QTDIR)
+			continue;
+
+		apath = estrjoin(m->name, d[i].name, nil);
+		a = mesgload(apath);
+		free(apath);
+		if(a == nil)
+			continue;
+		m->attachments[m->nattachments++] = a;
+		if(a->filename != nil || a->disposition != nil && strcmp(a->disposition, "inline") != 0)
+			continue;
+		if(strcmp(a->type, "text/plain") == 0)
+			best = a;
+		else if(best == nil && strcmp(a->type, "text/html") == 0)
+			best = a;
+	}
+	free(d);
+	if(best == nil)
+		return nil;
+	return best;
+}
+
+static void
+copy(int wfd, int rfd)
+{
+	char *buf;
 	int n;
 
 	buf = emalloc(Bufsz);
-	path = estrjoin(mbox.path, m->name, "body", nil);
-	if((wfd = winopen(m, "body", OWRITE)) == -1)
-		return -1;
-	if((rfd = open(path, OREAD)) == -1)
-		return -1;
-	fprint(wfd, "From: %s\n", m->from);
-	fprint(wfd, "Date: %s\n", m->to);
-	fprint(wfd, "Subject: %s\n\n", m->subject);
 	while(1){
 		n = read(rfd, buf, Bufsz);
 		if(n <= 0)
@@ -151,11 +187,57 @@
 		if(write(wfd, buf, n) != n)
 			break;
 	}
-	close(rfd);
-	close(wfd);
 	free(buf);
+}
+
+static int
+mesgshow(Mesg *m)
+{
+	char *path, *home, *name;
+	int i, rfd, wfd;
+	Mesg *a, *b;
+
+	if((wfd = winopen(m, "body", OWRITE)) == -1)
+		return -1;
+	fprint(wfd, "From: %s\n", m->from);
+	fprint(wfd, "Date: %s\n", m->date);
+	fprint(wfd, "Subject: %s\n\n", m->subject);
+
+	b = readparts(m);
+	path = estrjoin(mbox.path, b->name, "body", nil);
+	if(strcmp(b->type, "text/html"))
+		rfd = open(path, OREAD);//htmlfmt(path);
+	else
+		rfd = open(path, OREAD);
 	free(path);
-	return n;
+	if(rfd != -1){
+		copy(wfd, rfd);
+		close(rfd);
+	}
+
+	home = getenv("home");
+	for(i = 0; i < m->nattachments; i++){
+		a = m->attachments[i];
+		if(a == b)
+			continue;
+		fprint(wfd, "===> %s (%s)\n", a->name, a->type);
+		if(a->disposition != nil && strcmp(a->disposition, "inline") == 0){
+			path = estrjoin(mbox.path, b->name, "body", nil);
+			if((rfd = open(path, OREAD)) != -1){
+				copy(wfd, rfd);
+				close(rfd);
+			}
+		}else{
+			name = a->filename;
+			if(name == nil)
+				name = "body";
+			fprint(wfd, "\tcp %s%sbody %s/%s\n", mbox.path, a->name, home, name);
+			continue;
+		}
+	}
+	close(wfd);
+	free(home);
+	return 0;
 }
 
 static void