about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2021-06-18 00:44:47 +0200
committerLeah Neukirchen <leah@vuxu.org>2021-06-18 01:13:03 +0200
commit4e0de11300991ef0c1372fb831cef467be0e108a (patch)
tree138a05dcd3df840dcea5a3215adbb857cf2690d9
parent9713264f70846d6eda3d9ed97d0212c5a077f888 (diff)
downloadmblaze-4e0de11300991ef0c1372fb831cef467be0e108a.tar.gz
mblaze-4e0de11300991ef0c1372fb831cef467be0e108a.tar.xz
mblaze-4e0de11300991ef0c1372fb831cef467be0e108a.zip
mmime: print_header: encode quoted-strings at once
This is maybe a foul compromise between correctness and complexity of
implementation, but it should do the right thing in most cases, and
does not require fully parsing and reconstructing all headers that can
contain phrases.

An 'encoded-word' MUST NOT appear within a 'quoted-string'.  We thus
completely encode the quoted-string (if necessary) as a single
encoded-word, and strip off the quotes.

This should fix encoding of addresses that have both non-ASCII and
special chars such as , and ;.
-rw-r--r--mmime.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/mmime.c b/mmime.c
index b55d301..793cb31 100644
--- a/mmime.c
+++ b/mmime.c
@@ -317,12 +317,29 @@ print_header(char *line) {
 
 	while (*s) {
 		size_t highbit = 0;
+		int qs = 0;
 		e = s;
 		while (*e && *e == ' ')
 			e++;
-		for (; *e && *e != ' '; e++) {
-			if ((uint8_t)*e >= 127)
-				highbit++;
+
+		if (*e == '"') {  // scan quoted-string, encode at once
+			s = e;
+			for (e++; *e && *e != '"'; e++) {
+				if (*e == '\\')
+					e++;
+				if ((uint8_t)*e >= 127)
+					highbit++;
+			}
+			if (*e == '"')
+				e++;
+			qs = 1;
+		} else {  // scan word
+			while (*e && *e == ' ')
+				e++;
+			for (; *e && *e != ' '; e++) {
+				if ((uint8_t)*e >= 127)
+					highbit++;
+			}
 		}
 
 		if (!highbit) {
@@ -348,6 +365,12 @@ print_header(char *line) {
 force_qp:
 			if (!prevq && *s == ' ')
 				s++;
+
+			if (qs && *s == '"')
+				s++;
+			if (qs && e > s && *(e-1) == '"')
+				e--;
+
 			if (linelen >= 78 - 13 - 4 ||
 			    (e-s < (78 - 13)/3 &&
 			     e-s >= (78 - linelen - 13)/3)) {
@@ -361,6 +384,9 @@ force_qp:
 			printf("?=");
 			linelen += 2;
 			prevq = 1;
+
+			if (qs && *e == '"')
+				e++;
 		}
 		s = e;
 	}