about summary refs log tree commit diff
path: root/mmime.c
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 /mmime.c
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 ;.
Diffstat (limited to 'mmime.c')
-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;
 	}