changeset 4:612c4d0df768

f-demime: rework for unboundedly long lines
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 06 May 2023 09:02:12 +0000
parents 7a6cd16689f5
children 882d97266174
files f-demime/defs.h f-demime/finish.c f-demime/header.c f-demime/main.c f-demime/msgstate.c f-demime/qpdec.c
diffstat 6 files changed, 77 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/f-demime/defs.h	Sat May 06 06:41:20 2023 +0000
+++ b/f-demime/defs.h	Sat May 06 09:02:12 2023 +0000
@@ -5,6 +5,7 @@
 
 enum msg_state {
 	MSG_STATE_UNDEF,	/* before From line */
+	MSG_STATE_DELIM_UNTERM,	/* unterminated previous delimiter line */
 	MSG_STATE_HEADER,	/* message or body part header */
 	MSG_STATE_BODY_PASS,	/* body pass-through state */
 	MSG_STATE_PTEXT_B64,	/* text/plain decoding from base64 */
--- a/f-demime/finish.c	Sat May 06 06:41:20 2023 +0000
+++ b/f-demime/finish.c	Sat May 06 09:02:12 2023 +0000
@@ -32,10 +32,16 @@
 {
 	switch (msg_state) {
 	case MSG_STATE_HEADER:
-		if (got_cont_type)
+		if (got_cont_type) {
 			fputs(cont_type_buf, stdout);
-		if (got_cont_te)
+			if (cont_type_buf[strlen(cont_type_buf)-1] != '\n')
+				putchar('\n');
+		}
+		if (got_cont_te) {
 			fputs(cont_te_buf, stdout);
+			if (cont_te_buf[strlen(cont_te_buf)-1] != '\n')
+				putchar('\n');
+		}
 		return;
 	case MSG_STATE_PTEXT_B64:
 		base64_dec_finish();
--- a/f-demime/header.c	Sat May 06 06:41:20 2023 +0000
+++ b/f-demime/header.c	Sat May 06 09:02:12 2023 +0000
@@ -27,7 +27,7 @@
 		got_cont_te = 0;
 	}
 	printf("X-Fdemime-Error: %s\n", msg);
-	puts(line);
+	fputs(line, stdout);
 	hdr_state = HDR_STATE_ERROR;
 }
 
@@ -49,31 +49,31 @@
 		error(line, "continuation line at the beginning of header");
 		return;
 	case HDR_STATE_GOTSOME:
-		puts(line);
+		fputs(line, stdout);
 		return;
 	case HDR_STATE_CONT_TYPE:
 		prev_len = strlen(cont_type_buf);
-		if (prev_len + strlen(line) + 2 > HDR_BUF_SIZE) {
+		if (prev_len + strlen(line) + 1 > HDR_BUF_SIZE) {
 			error_ct_cont("Content-Type");
 			fputs(cont_type_buf, stdout);
-			puts(line);
+			fputs(line, stdout);
 			hdr_state = HDR_STATE_ERROR;
 			got_cont_type = 0;
 			return;
 		}
-		sprintf(cont_type_buf + prev_len, "%s\n", line);
+		strcpy(cont_type_buf + prev_len, line);
 		return;
 	case HDR_STATE_CONT_TE:
 		prev_len = strlen(cont_te_buf);
-		if (prev_len + strlen(line) + 2 > HDR_BUF_SIZE) {
+		if (prev_len + strlen(line) + 1 > HDR_BUF_SIZE) {
 			error_ct_cont("Content-Transfer-Encoding");
 			fputs(cont_te_buf, stdout);
-			puts(line);
+			fputs(line, stdout);
 			hdr_state = HDR_STATE_ERROR;
 			got_cont_te = 0;
 			return;
 		}
-		sprintf(cont_te_buf + prev_len, "%s\n", line);
+		strcpy(cont_te_buf + prev_len, line);
 		return;
 	default:
 		fprintf(stderr,
@@ -83,21 +83,21 @@
 }
 
 void
-header_input_line(line)
+header_input_line(line, unterm, prev_unterm)
 	char *line;
 {
 	char *cp, savech;
 	enum msg_hdr_state newhdr;
 
-	if (!line[0]) {
+	if (!prev_unterm && line[0] == '\n') {
 		process_header_end();
 		return;
 	}
 	if (hdr_state == HDR_STATE_ERROR) {
-		puts(line);
+		fputs(line, stdout);
 		return;
 	}
-	if (line[0] == ' ' || line[0] == '\t') {
+	if (prev_unterm || line[0] == ' ' || line[0] == '\t') {
 		cont_line(line);
 		return;
 	}
@@ -127,7 +127,7 @@
 			error(line, "duplicate Content-Type");
 			return;
 		}
-		sprintf(cont_type_buf, "%s\n", line);
+		strcpy(cont_type_buf, line);
 		got_cont_type = 1;
 		break;
 	case HDR_STATE_CONT_TE:
@@ -135,11 +135,11 @@
 			error(line, "duplicate Content-Transfer-Encoding");
 			return;
 		}
-		sprintf(cont_te_buf, "%s\n", line);
+		strcpy(cont_te_buf, line);
 		got_cont_te = 1;
 		break;
 	default:
-		puts(line);
+		fputs(line, stdout);
 	}
 	hdr_state = newhdr;
 }
--- a/f-demime/main.c	Sat May 06 06:41:20 2023 +0000
+++ b/f-demime/main.c	Sat May 06 09:02:12 2023 +0000
@@ -15,7 +15,6 @@
 #include "defs.h"
 
 char *att_filename_buf, *att_filename_base, *att_filename_tail;
-unsigned input_lineno;
 
 static void
 get_attachment_dir()
@@ -60,7 +59,9 @@
 main(argc, argv)
 	char **argv;
 {
-	char linebuf[LINE_BUF_SIZE], *cp;
+	char linebuf[LINE_BUF_SIZE];
+	int c, unterm, prev_unterm;
+	unsigned lineno;
 
 	if (argc > 3) {
 		fprintf(stderr, "usage: %s [infile [outfile]]\n", argv[0]);
@@ -75,25 +76,34 @@
 		perror(argv[2]);
 		exit(1);
 	}
-	for (input_lineno = 1; fgets(linebuf, sizeof linebuf, stdin);
-	     input_lineno++) {
-		cp = index(linebuf, '\n');
-		if (cp) {
-			*cp = '\0';
-			if (cp > linebuf && cp[-1] == '\r')
-				*--cp = '\0';
-		} else {
-			fprintf(stderr,
-		"f-demime warning: input line %u too long or unterminated\n",
-				input_lineno);
-		}
-		if (!strncmp(linebuf, "From ", 5)) {
+	lineno = 0;
+	for (prev_unterm = 0; fgets(linebuf, sizeof linebuf, stdin);
+	     prev_unterm = unterm) {
+		if (!prev_unterm)
+			lineno++;
+		if (index(linebuf, '\n'))
+			unterm = 0;
+		else
+			unterm = 1;
+		if (!prev_unterm && !strncmp(linebuf, "From ", 5)) {
 			finish_msg_body();
-			puts(linebuf);
+			fputs(linebuf, stdout);
+			if (unterm) {
+				fprintf(stderr,
+		"f-demime warning: From line %u too long or unterminated\n",
+					lineno);
+				for (;;) {
+					c = getchar();
+					if (c == EOF || c == '\n')
+						break;
+				}
+				putchar('\n');
+				unterm = 0;
+			}
 			begin_new_message();
 			continue;
 		}
-		message_input_line(linebuf);
+		message_input_line(linebuf, unterm, prev_unterm);
 	}
 	finish_msg_body();
 	exit(0);
--- a/f-demime/msgstate.c	Sat May 06 06:41:20 2023 +0000
+++ b/f-demime/msgstate.c	Sat May 06 09:02:12 2023 +0000
@@ -47,7 +47,7 @@
 }
 
 static int
-check_mp_terminator(line)
+check_mp_terminator(line, unterm)
 	char *line;
 {
 	unsigned lev, bndlen;
@@ -61,15 +61,19 @@
 		if (strncmp(line+2, bnd, bndlen))
 			continue;
 		finish_msg_body();
-		puts(line);
+		fputs(line, stdout);
 		cp = line + 2 + bndlen;
 		if (!*cp || isspace(*cp)) {
 			mp_nest_level = lev + 1;
 			start_entity_hdr();
+			if (unterm)
+				msg_state = MSG_STATE_DELIM_UNTERM;
 			return(1);
 		}
-		if (cp[0] != '-' || cp[1] != '-')
-			puts("X-Fdemime-Error: invalid delimiter line");
+		if (cp[0] != '-' || cp[1] != '-') {
+			if (!unterm)
+				puts("X-Fdemime-Error: invalid delimiter line");
+		}
 		mp_nest_level = lev;
 		msg_state = MSG_STATE_BODY_PASS;
 		return(1);
@@ -78,21 +82,26 @@
 }
 
 void
-message_input_line(line)
+message_input_line(line, unterm, prev_unterm)
 	char *line;
 {
-	if (check_mp_terminator(line))
+	if (!prev_unterm && check_mp_terminator(line, unterm))
 		return;
 	switch (msg_state) {
 	case MSG_STATE_UNDEF:
 		emit_prefrom_warning();
-		puts(line);
+		fputs(line, stdout);
+		return;
+	case MSG_STATE_DELIM_UNTERM:
+		fputs(line, stdout);
+		if (!unterm)
+			msg_state = MSG_STATE_HEADER;
 		return;
 	case MSG_STATE_HEADER:
-		header_input_line(line);
+		header_input_line(line, unterm, prev_unterm);
 		return;
 	case MSG_STATE_BODY_PASS:
-		puts(line);
+		fputs(line, stdout);
 		return;
 	case MSG_STATE_PTEXT_B64:
 	case MSG_STATE_BLOB_B64:
@@ -100,7 +109,7 @@
 		base64_input_line(line);
 		return;
 	case MSG_STATE_PTEXT_QP:
-		qpdec_input_line(line);
+		qpdec_input_line(line, unterm);
 		return;
 	default:
 		fprintf(stderr,
--- a/f-demime/qpdec.c	Sat May 06 06:41:20 2023 +0000
+++ b/f-demime/qpdec.c	Sat May 06 09:02:12 2023 +0000
@@ -48,7 +48,7 @@
 }
 
 void
-qpdec_input_line(line)
+qpdec_input_line(line, unterm)
 	char *line;
 {
 	char *cp;
@@ -61,8 +61,11 @@
 			dec_outf(c);
 			continue;
 		}
-		if (!*cp)
+		if (!*cp) {
+			if (unterm)
+				qpdec_err_flag = 1;
 			return;
+		}
 		if (isxdigit(cp[0]) && isxdigit(cp[1])) {
 			c = decode_hex_byte(cp);
 			cp += 2;
@@ -72,5 +75,6 @@
 		qpdec_err_flag = 1;
 		dec_outf('=');
 	}
-	dec_outf('\n');
+	if (!unterm)
+		dec_outf('\n');
 }