about summary refs log tree commit diff
path: root/blaze822.c
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2016-07-13 15:22:47 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2016-07-13 15:22:47 +0200
commit7c0663e0e52361461f525db546d324f40de5c61e (patch)
treeb94b618781dfac8eb58d6a37a860e2ed115c3e68 /blaze822.c
parent0552c3708e3e16d7501262ff049eec54b60d9d57 (diff)
downloadmblaze-7c0663e0e52361461f525db546d324f40de5c61e.tar.gz
mblaze-7c0663e0e52361461f525db546d324f40de5c61e.tar.xz
mblaze-7c0663e0e52361461f525db546d324f40de5c61e.zip
blaze822: don't prefix first header with nul bytes
Instead, look for the first header as a special case.
This allows us to parse a header as-is without shifting in memory.
Diffstat (limited to 'blaze822.c')
-rw-r--r--blaze822.c184
1 files changed, 73 insertions, 111 deletions
diff --git a/blaze822.c b/blaze822.c
index 31ef844..33caba1 100644
--- a/blaze822.c
+++ b/blaze822.c
@@ -227,6 +227,52 @@ blaze822_addr(char *s, char **dispo, char **addro)
 	return s;
 }
 
+static void
+unfold_hdr(char *buf, char *end)
+{
+	char *s = buf;
+
+	while (s < end && *s != ':') {
+		*s = lc(*s);
+		s++;
+	}
+
+	for (; s < end; s++) {
+		if (*s == 0)   // sanitize nul bytes in headers
+			*s = ' ';
+
+		if (*s == '\r') {
+			if (*(s+1) == '\n') {
+				*s++ = '\n';
+			} else {
+				*s = ' ';
+			}
+		}
+
+		if (iswsp(*s)) {
+			// change prior \n to spaces
+			int j;
+			for (j = 1; s - j >= buf && *(s-j) == '\n'; j++)
+				*(s-j) = ' ';
+		}
+
+		if (*s == '\n') {
+			s++;
+			if (iswsp(*s)) {
+				*(s-1) = ' ';
+			} else {
+				*(s-1) = 0;
+				if (s-2 > buf && *(s-2) == '\n')   // ex-crlf
+					*(s-2) = 0;
+				while (s < end && *s != ':') {
+					*s = lc(*s);
+					s++;
+				}
+			}
+		}
+	}
+}
+
 struct message *
 blaze822(char *file)
 {
@@ -237,25 +283,27 @@ blaze822(char *file)
 	ssize_t used;
 	char *end;
 
+	struct message *mesg = malloc(sizeof (struct message));
+	if (!mesg)
+		return 0;
+
 	fd = open(file, O_RDONLY);
 	if (fd < 0) {
 //		perror("open");
 		return 0;
 	}
 
-	buf = malloc(3);
-	if (!buf)
-		return 0;
-	buf[0] = '\n';
-	buf[1] = '\n';
-	buf[2] = '\n';
-	bufalloc = 3;
-	used = 3;
+	buf = 0;
+	bufalloc = 0;
+	used = 0;
 
 	while (1) {
+		int overlap = used > 3 ? 3 : 0;
+
 		bufalloc += bufsiz;
 		buf = realloc(buf, bufalloc);
 		if (!buf) {
+			free(mesg);
 			close(fd);
 			return 0;
 		}
@@ -266,13 +314,14 @@ blaze822(char *file)
 			break;
 		}
 		if (rd < 0) {
+			free(mesg);
 			free(buf);
 			close(fd);
 			return 0;
 		}
 
-		if ((end = memmem(buf-1+used, rd+1, "\n\n", 2)) ||
-		    (end = memmem(buf-3+used, rd+3, "\r\n\r\n", 4))) {
+		if ((end = memmem(buf-overlap+used, rd+overlap, "\n\n", 2)) ||
+		    (end = memmem(buf-overlap+used, rd+overlap, "\r\n\r\n", 4))) {
 			used += rd;
 			end++;
 			break;
@@ -284,51 +333,7 @@ blaze822(char *file)
 
 	*end = 0;   // dereferencing *end is safe
 
-	char *s;
-	for (s = buf; s < end; s++) {
-		if (*s == 0)   // sanitize nul bytes in headers
-			*s = ' ';
-
-		if (*s == '\r') {
-			if (*(s+1) == '\n') {
-				*s++ = '\n';
-			} else {
-				*s = ' ';
-			}
-		}
-
-		if (iswsp(*s)) {
-			// change prior \n to spaces
-			int j;
-			for (j = 1; s - j >= buf && *(s-j) == '\n'; j++)
-				*(s-j) = ' ';
-		}
-
-		if (*s == '\n') {
-			s++;
-			if (iswsp(*s)) {
-				*(s-1) = ' ';
-			} else {			
-				*(s-1) = 0;
-				if (s-2 > buf && *(s-2) == '\n')   // ex-crlf
-					*(s-2) = 0;
-				while (s < end && *s != ':') {
-					*s = lc(*s);
-					s++;
-				}
-			}
-		}
-	}
-
-	buf[0] = 0;
-	buf[1] = 0;
-	buf[2] = 0;
-
-	struct message *mesg = malloc(sizeof (struct message));
-	if (!mesg) {
-		free(buf);
-		return 0;
-	}
+	unfold_hdr(buf, end);
 
 	mesg->msg = buf;
 	mesg->end = end;
@@ -345,12 +350,9 @@ blaze822_mem(char *src, size_t len)
 	char *buf;
 	char *end;
 
-	buf = malloc(3);
-	if (!buf)
+	struct message *mesg = malloc(sizeof (struct message));
+	if (!mesg)
 		return 0;
-	buf[0] = '\n';
-	buf[1] = '\n';
-	buf[2] = '\n';
 
 	end = memmem(src, len, "\n\n", 2);
 	if (!end) end = memmem(src, len, "\r\n\r\n", 4);
@@ -358,59 +360,15 @@ blaze822_mem(char *src, size_t len)
 
 	len = end - src;
 
-	buf = realloc(buf, len+3+1);
-	memcpy(buf+3, src, len);
+	buf = malloc(len+1);
+	if (!buf)
+		return 0;
+	memcpy(buf, src, len);
 
-	end = buf+3+1+len;
+	end = buf+len+1;
 	*end = 0;   // dereferencing *end is safe
 
-	/// XXX merge with below
-
-	char *s;
-	for (s = buf; s < end; s++) {
-		if (*s == 0)   // sanitize nul bytes in headers
-			*s = ' ';
-
-		if (*s == '\r') {
-			if (*(s+1) == '\n') {
-				*s++ = '\n';
-			} else {
-				*s = ' ';
-			}
-		}
-
-		if (iswsp(*s)) {
-			// change prior \n to spaces
-			int j;
-			for (j = 1; s - j >= buf && *(s-j) == '\n'; j++)
-				*(s-j) = ' ';
-		}
-
-		if (*s == '\n') {
-			s++;
-			if (iswsp(*s)) {
-				*(s-1) = ' ';
-			} else {
-				*(s-1) = 0;
-				if (s-2 > buf && *(s-2) == '\n')   // ex-crlf
-					*(s-2) = 0;
-				while (s < end && *s != ':') {
-					*s = lc(*s);
-					s++;
-				}
-			}
-		}
-	}
-
-	buf[0] = 0;
-	buf[1] = 0;
-	buf[2] = 0;
-
-	struct message *mesg = malloc(sizeof (struct message));
-	if (!mesg) {
-		free(buf);
-		return 0;
-	}
+	unfold_hdr(buf, end);
 
 	mesg->msg = buf;
 	mesg->end = end;
@@ -440,7 +398,11 @@ blaze822_hdr_(struct message *mesg, const char *hdr, size_t hdrlen)
 {
 	char *v;
 
-	v = memmem(mesg->msg, mesg->end - mesg->msg, hdr, hdrlen);
+	// special case: first header, no leading nul
+	if (memcmp(mesg->msg, hdr+1, hdrlen-1) == 0)
+		v = mesg->msg;
+	else
+		v = memmem(mesg->msg, mesg->end - mesg->msg, hdr, hdrlen);
 	if (!v)
 		return 0;
 	v += hdrlen;