about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--blaze822.c130
-rw-r--r--blaze822.h2
2 files changed, 132 insertions, 0 deletions
diff --git a/blaze822.c b/blaze822.c
index 4aab311..31ef844 100644
--- a/blaze822.c
+++ b/blaze822.c
@@ -332,14 +332,106 @@ blaze822(char *file)
 
 	mesg->msg = buf;
 	mesg->end = end;
+	mesg->body = 0;
+	mesg->bodyend = 0;
 
 	return mesg;
 }
 
+
+struct message *
+blaze822_mem(char *src, size_t len)
+{
+	char *buf;
+	char *end;
+
+	buf = malloc(3);
+	if (!buf)
+		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);
+	if (!end) end = src + len;
+
+	len = end - src;
+
+	buf = realloc(buf, len+3+1);
+	memcpy(buf+3, src, len);
+
+	end = buf+3+1+len;
+	*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;
+	}
+
+	mesg->msg = buf;
+	mesg->end = end;
+	mesg->body = 0;
+	mesg->bodyend = 0;
+
+	return mesg;
+}
+
+void
+blaze822_mem_body(struct message *mesg, char *buf, size_t len)
+{
+	mesg->body = buf + (mesg->end - mesg->msg - 2);
+	mesg->bodyend = buf + len - (mesg->end - mesg->msg - 2);
+}
+
 void
 blaze822_free(struct message *mesg)
 {
 	free(mesg->msg);
+	// XXX body? keep track who malloced it?
 	free(mesg);
 }
 
@@ -395,3 +487,41 @@ blaze822_body(struct message *mesg, char *file)
 
 	return fd;
 }
+
+int
+blaze822_file_body(struct message *mesg, char *file)
+{
+	int fd = open(file, O_RDONLY);
+	if (fd < 0)
+		return fd;
+
+	struct stat st;
+	if (fstat(fd, &st) < 0)
+		goto error;
+
+	if (lseek(fd, mesg->end - mesg->msg - 2, SEEK_SET) < 0) {
+		perror("lseek");
+		goto error;
+	}
+
+	size_t s = st.st_size - (mesg->end - mesg->msg - 2);
+
+	char *body = malloc(s+1);
+	if (read(fd, body, s) < 0) {
+		// XXX handle short reads?
+		perror("read");
+		goto error;
+	}
+	body[s] = 0;
+
+	mesg->body = body;
+	mesg->bodyend = body+s;
+
+	close(fd);
+	return 1;
+
+error:
+	close(fd);
+	return -1;
+}
+
diff --git a/blaze822.h b/blaze822.h
index 7785b75..2705084 100644
--- a/blaze822.h
+++ b/blaze822.h
@@ -3,10 +3,12 @@
 struct message;
 
 struct message *blaze822(char *file);
+struct message *blaze822_mem(char *buf, size_t len);
 void blaze822_free(struct message *mesg);
 char *blaze822_hdr_(struct message *mesg, const char *hdr, size_t len);
 #define blaze822_hdr(mesg, hdr) blaze822_hdr_(mesg, "\0" hdr ":", 2+strlen((hdr)))
 int blaze822_body(struct message *mesg, char *file);
+void blaze822_mem_body(struct message *mesg, char *buf, size_t len);
 
 int blaze822_loop(int, char **, void (*)(char *));