git: beab8b1ddf86 - main - bintrans(1): RFC2047 variant of quoted print

From: Baptiste Daroussin <bapt_at_FreeBSD.org>
Date: Thu, 09 Jan 2025 09:27:27 UTC
The branch main has been updated by bapt:

URL: https://cgit.FreeBSD.org/src/commit/?id=beab8b1ddf86a88e0605562f2cc1d6a26c68604f

commit beab8b1ddf86a88e0605562f2cc1d6a26c68604f
Author:     Baptiste Daroussin <bapt@FreeBSD.org>
AuthorDate: 2025-01-08 12:39:30 +0000
Commit:     Baptiste Daroussin <bapt@FreeBSD.org>
CommitDate: 2025-01-09 09:27:18 +0000

    bintrans(1): RFC2047 variant of quoted print
    
    MFC After:      1 week
    Reviewed by:    pstref
    Differential Revision:  https://reviews.freebsd.org/D48381
---
 usr.bin/bintrans/bintrans.1 |  2 ++
 usr.bin/bintrans/qp.c       | 32 +++++++++++++++++++++++---------
 2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/usr.bin/bintrans/bintrans.1 b/usr.bin/bintrans/bintrans.1
index 4177a5c6b9eb..02571067c8f0 100644
--- a/usr.bin/bintrans/bintrans.1
+++ b/usr.bin/bintrans/bintrans.1
@@ -236,6 +236,8 @@ Decode.
 Output to
 .Ar output_file
 instead of standard output.
+.It fl r
+Encode/Decode in RFC2047 specific variant.
 .El
 .Sh EXAMPLES
 The following example packages up a source tree, compresses it,
diff --git a/usr.bin/bintrans/qp.c b/usr.bin/bintrans/qp.c
index 3bff47945acf..862db437f4e0 100644
--- a/usr.bin/bintrans/qp.c
+++ b/usr.bin/bintrans/qp.c
@@ -51,7 +51,7 @@ decode_char(const char *s)
 
 
 static void
-decode_quoted_printable(const char *body, FILE *fpo)
+decode_quoted_printable(const char *body, FILE *fpo, bool rfc2047)
 {
 	while (*body != '\0') {
 		switch (*body) {
@@ -80,6 +80,12 @@ decode_quoted_printable(const char *body, FILE *fpo)
 			fputc(decode_char(body), fpo);
 			body += 2;
 			break;
+		case '_':
+			if (rfc2047) {
+				fputc(0x20, fpo);
+				break;
+			}
+			/* FALLTHROUGH */
 		default:
 			fputc(*body, fpo);
 			break;
@@ -89,7 +95,7 @@ decode_quoted_printable(const char *body, FILE *fpo)
 }
 
 static void
-encode_quoted_printable(const char *body, FILE *fpo)
+encode_quoted_printable(const char *body, FILE *fpo, bool rfc2047)
 {
 	const char *end = body + strlen(body);
 	size_t linelen = 0;
@@ -111,7 +117,10 @@ encode_quoted_printable(const char *body, FILE *fpo)
 			if ((*body == ' ' || *body == '\t') &&
 			    body + 1 < end &&
 			    (body[1] != '\n' && body[1] != '\r')) {
-				fputc(*body, fpo);
+				if (*body == 0x20 && rfc2047)
+					fputc('_', fpo);
+				else
+					fputc(*body, fpo);
 				prev = *body;
 			} else {
 				fprintf(fpo, "=%02X", (unsigned char)*body);
@@ -135,16 +144,16 @@ encode_quoted_printable(const char *body, FILE *fpo)
 }
 
 static void
-qp(FILE *fp, FILE *fpo, bool encode)
+qp(FILE *fp, FILE *fpo, bool encode, bool rfc2047)
 {
 	char *line = NULL;
 	size_t linecap = 0;
-	void (*codec)(const char *line, FILE *f);
+	void (*codec)(const char *line, FILE *f, bool rfc2047);
 
 	codec = encode ? encode_quoted_printable : decode_quoted_printable ;
 
 	while (getline(&line, &linecap, fp) > 0)
-		codec(line, fpo);
+		codec(line, fpo, rfc2047);
 	free(line);
 }
 
@@ -152,7 +161,7 @@ static void
 usage(void)
 {
 	fprintf(stderr,
-	   "usage: bintrans qp [-d] [-o outputfile] [file name]\n");
+	   "usage: bintrans qp [-d] [-r] [-o outputfile] [file name]\n");
 }
 
 int
@@ -160,6 +169,7 @@ main_quotedprintable(int argc, char *argv[])
 {
 	int ch;
 	bool encode = true;
+	bool rfc2047 = false;
 	FILE *fp = stdin;
 	FILE *fpo = stdout;
 
@@ -167,10 +177,11 @@ main_quotedprintable(int argc, char *argv[])
 	{
 		{ "decode", no_argument,		NULL, 'd'},
 		{ "output", required_argument,		NULL, 'o'},
+		{ "rfc2047", no_argument,		NULL, 'r'},
 		{NULL,		no_argument,		NULL, 0}
 	};
 
-	while ((ch = getopt_long(argc, argv, "do:u", opts, NULL)) != -1) {
+	while ((ch = getopt_long(argc, argv, "do:ru", opts, NULL)) != -1) {
 		switch(ch) {
 		case 'o':
 			fpo = fopen(optarg, "w");
@@ -184,6 +195,9 @@ main_quotedprintable(int argc, char *argv[])
 		case 'd':
 			encode = false;
 			break;
+		case 'r':
+			rfc2047 = true;
+			break;
 		default:
 			usage();
 			exit(EXIT_FAILURE);
@@ -198,7 +212,7 @@ main_quotedprintable(int argc, char *argv[])
 			exit(EXIT_FAILURE);
 		}
 	}
-	qp(fp, fpo, encode);
+	qp(fp, fpo, encode, rfc2047);
 
 	return (EXIT_SUCCESS);
 }