Thorsten Glaser wrote:
> 
>> Mind you, I am also open to reviewing his proposal of
>> adding those headers even with -a (letting -a override the
>> auto-generated ones when there is a conflict).

I was thinking how to implement this functionality, and during that I
realized that it actually would nice not to add the headers if the mail
content is 7-bit only. I even tried to write some code for this, but it
would require too many changes, so I gave up the idea for now.

Anyway after a few attempts I ended with the attached patch. It allows
user to override the headers, however it touches different parts of code
than your original patch, mostly because of my failed attempt of 7 vs 8
bit mail content detection. It potentially has slightly worse
performance due to parsing of the user-provider headers after they have
been already joined by "\n" chars, but on the other hand it does not
allocate additional memory via asprintf(). What do you think about it?

> 
> Robert, Niels, what do you think about the attached patch?

The patch looks OK. The addition of -D_GNU_SOURCE flag causes warnings
during compilation of files that already #define _GNU_SOURCE, but this
is easy to fix by using #define in main.c.


I would like to prepare an upload tomorrow. Could you please let me know
which patch you prefer: the original one or the one attached to this mail?

Regards,
robert
From: Robert Luberda <rob...@debian.org>
Date: Thu, 13 Apr 2017 23:39:39 +0200
Subject: Add MIME headers unless set by user

Generate the three following headers by default:
  MIME-Version: 1.0
  Content-Type: text/plain; charset="<current charset from $LC_CTYPE>"
  Content-Transfer-Encoding: 8bit

However allow a user to override each of them with the -a flag.
Example:
   bsd-mailx -a "Content-Type: text/html; charset=UTF-8"
uses the above user-provided Content-Type, but still adds
the default MIME-Version and Content-Transfer-Encoding headers.

Bugs-Debian: https://bugs.debian.org/859935
---
 main.c |  4 ++++
 send.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/main.c b/main.c
index 07ad856..4cba833 100644
--- a/main.c
+++ b/main.c
@@ -34,6 +34,7 @@
 #include <fcntl.h>
 #include <sys/ioctl.h>
 #include "extern.h"
+#include <locale.h>
 
 static void	usage(void);
 	int	main(int, char **);
@@ -70,6 +71,9 @@ main(int argc, char **argv)
           err(1, "setuid");
 	}
 
+	/* Set the current user locale's charset. */
+	setlocale(LC_CTYPE, "");
+
 	/*
 	 * Set up a reasonable environment.
 	 * Figure out whether we are being run interactively,
diff --git a/send.c b/send.c
index cc75f49..771ecc9 100644
--- a/send.c
+++ b/send.c
@@ -30,6 +30,7 @@
  * SUCH DAMAGE.
  */
 
+#include <langinfo.h>
 #include <time.h>
 #include "rcv.h"
 #include "extern.h"
@@ -558,6 +559,36 @@ infix(struct header *hp, FILE *fi)
 	rewind(nfi);
 	return(nfi);
 }
+/*
+ * Check if headers (a list separated by new line characters) contains a header
+ * which name is given in the headername argument of length given in headernamelen.
+ */
+static int hasheader(const char* headers, const char* const headername, const size_t headernamelen)
+{
+	while (headers) {
+		/*  Skip leading white spaces, including '\n' from
+		 *  the previous iteration of the loop
+		 */
+		while (isspace(*headers))
+			++headers;
+
+		if (strncasecmp(headers, headername, headernamelen) == 0) {
+			/* Found a match, check if it is followed by ':' */
+			const char* end = headers + headernamelen;
+			/* Permit optional white spaces before ':' */
+			while (isspace(*end) && *end != '\n')
+				++end;
+
+			if (*end == ':')
+				return 1;
+
+			headers = end; /* Small optimization for the following strchr() call */
+		}
+
+		headers = strchr(headers, '\n'); /* Find start of the next header */
+	}
+	return 0;
+}
 
 /*
  * Dump the to, subject, cc header on the
@@ -583,6 +614,18 @@ puthead(struct header *hp, FILE *fo, int w)
 		fmt("Bcc:", hp->h_bcc, fo, w&GCOMMA), gotcha++;
 	if (hp->h_header != NULL && w)
 		fprintf(fo, "%s\n", hp->h_header), gotcha++;
+	if (w)
+	{
+#define ADDHEADER(name, value, ...) if (!hasheader(hp->h_header, name, sizeof(name) - 1)) \
+				     fprintf(fo, name ": " value "\n", ##__VA_ARGS__), gotcha++
+
+		const char* const cs = nl_langinfo(CODESET);
+		ADDHEADER("MIME-Version", "1.0");
+		ADDHEADER("Content-Type", "text/plain; charset=\"%s\"",
+				cs && *cs ? cs : "ANSI_X3.4-1968");
+		ADDHEADER("Content-Transfer-Encoding", "8bit");
+#undef ADDHEADER
+	}
         if (hp->h_replyto != NULL && w & GREPLYTO)
                 fprintf(fo, "Reply-To: %s\n", hp->h_replyto), gotcha++;
         if (hp->h_inreplyto != NULL && w & GINREPLYTO)

Reply via email to