about summary refs log tree commit diff
path: root/mmime.c
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2017-06-29 16:43:47 +0200
committerLeah Neukirchen <leah@vuxu.org>2017-06-29 16:43:47 +0200
commit613a1182ff9e8b5ca598e3d233a0e36386559e30 (patch)
treee309bf8ff4674f8c2e9599be7f539f0feb9a6022 /mmime.c
parent24d09410434b13c961f23e1985a482af605a9ed5 (diff)
downloadmblaze-613a1182ff9e8b5ca598e3d233a0e36386559e30.tar.gz
mblaze-613a1182ff9e8b5ca598e3d233a0e36386559e30.tar.xz
mblaze-613a1182ff9e8b5ca598e3d233a0e36386559e30.zip
mmime: gen_qp: ensure not to split utf8 multibyte sequences into encoded words
RFC2047, 5.(3):
> Each 'encoded-word' MUST represent an integral number of characters.
> A multi-octet character may not be split across adjacent 'encoded-
> word's.
Diffstat (limited to 'mmime.c')
-rw-r--r--mmime.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/mmime.c b/mmime.c
index 0aee314..5d667b9 100644
--- a/mmime.c
+++ b/mmime.c
@@ -64,6 +64,26 @@ int gen_qp(uint8_t *s, off_t size, int maxlinelen, int linelen)
 	char prev = 0;
 
 	for (i = 0; i < size; i++) {
+		// inspect utf8 sequence to not wrap in between multibyte
+		int mb;
+		if      ((s[i] & 0x80) == 0)    mb = 3;
+		else if ((s[i] & 0xc0) == 0x80) mb = 3;
+		else if ((s[i] & 0xe0) == 0xc0) mb = 6;
+		else if ((s[i] & 0xf0) == 0xe0) mb = 9;
+		else if ((s[i] & 0xf8) == 0xf0) mb = 12;
+		else mb = 3;
+
+		if (linelen >= maxlinelen-mb-!!header) {
+			linelen = 0;
+			prev = '\n';
+			if (header) {
+				printf("?=\n =?UTF-8?Q?");
+				linelen += 11;
+			} else {
+				puts("=");
+			}
+		}
+
 		if ((s[i] > 126) ||
 		    (s[i] < 32 && s[i] != '\n' && s[i] != '\t') ||
 		    (s[i] == '=')) {
@@ -90,17 +110,6 @@ int gen_qp(uint8_t *s, off_t size, int maxlinelen, int linelen)
 			linelen++;
 			prev = s[i];
 		}
-		
-		if (linelen >= maxlinelen-3-!!header) {
-			linelen = 0;
-			prev = '\n';
-			if (header) {
-				printf("?=\n =?UTF-8?Q?");
-				linelen += 11;
-			} else {
-				puts("=");
-			}
-		}
 	}
 	if (linelen > 0 && !header)
 		puts("=");