Bug#860022: Bug#859935: Bug#860022: unblock: bsd-mailx/8.1.2-0.20160123cvs-3.1 (pre-approval)
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 <robert@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 to: