summary refs log tree commit diff
path: root/imap.c
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2020-05-01 17:15:22 -0400
committerJune McEnroe <june@causal.agency>2020-05-01 17:20:45 -0400
commiteeed8059e2eca4e078f2b95ae6650963b3edfd2e (patch)
tree3cc786d51b298e181bea4220fa3ab5e47db74d4b /imap.c
parentRemove unused includes (diff)
downloadimbox-eeed8059e2eca4e078f2b95ae6650963b3edfd2e.tar.gz
imbox-eeed8059e2eca4e078f2b95ae6650963b3edfd2e.zip
Update IMAP parser
Diffstat (limited to '')
-rw-r--r--imap.c31
1 files changed, 13 insertions, 18 deletions
diff --git a/imap.c b/imap.c
index a5daaf6..7984e0e 100644
--- a/imap.c
+++ b/imap.c
@@ -60,10 +60,11 @@ static int imapClose(void *_tls) {
 	struct tls *tls = _tls;
 	int error = tls_close(tls);
 	if (error) errx(EX_IOERR, "tls_close: %s", tls_error(tls));
+	tls_free(tls);
 	return error;
 }
 
-FILE *imapOpen(const char *host, const char *port) {
+void imapOpen(FILE **read, FILE **write, const char *host, const char *port) {
 	struct tls *client = tls_client();
 	if (!client) errx(EX_SOFTWARE, "tls_client");
 
@@ -77,11 +78,11 @@ FILE *imapOpen(const char *host, const char *port) {
 	error = tls_connect(client, host, port);
 	if (error) errx(EX_NOHOST, "tls_connect: %s", tls_error(client));
 
-	FILE *imap = funopen(client, imapRead, imapWrite, NULL, imapClose);
-	if (!imap) err(EX_SOFTWARE, "funopen");
+	*read = funopen(client, imapRead, NULL, NULL, NULL);
+	*write = funopen(client, NULL, imapWrite, NULL, imapClose);
+	if (!*read || !*write) err(EX_SOFTWARE, "funopen");
 
-	setlinebuf(imap);
-	return imap;
+	setlinebuf(*write);
 }
 
 static size_t cap;
@@ -98,7 +99,7 @@ static void imapLine(FILE *imap) {
 }
 
 static struct Data parseAtom(void) {
-	size_t len = strcspn(ptr, " ()[]{\"");
+	size_t len = (*ptr == '.' ? 1 : strcspn(ptr, " .()[]{\""));
 	struct Data data = {
 		.type = Atom,
 		.atom = atomn(ptr, len),
@@ -149,18 +150,7 @@ static struct Data parseList(FILE *imap, char close) {
 	if (*ptr) ptr++;
 	struct Data data = { .type = List };
 	while (*ptr != close) {
-		if (data.list.len == data.list.cap) {
-			if (data.list.cap) {
-				data.list.cap *= 2;
-			} else {
-				data.list.cap = 4;
-			}
-			data.list.ptr = realloc(
-				data.list.ptr, sizeof(*data.list.ptr) * data.list.cap
-			);
-			if (!data.list.ptr) err(EX_OSERR, "realloc");
-		}
-		data.list.ptr[data.list.len++] = parseData(imap);
+		listPush(&data.list, parseData(imap));
 	}
 	if (*ptr) ptr++;
 	return data;
@@ -185,6 +175,11 @@ struct Resp imapResp(FILE *imap) {
 	data = parseData(imap);
 	if (data.type != Atom) errx(EX_PROTOCOL, "expected tag atom");
 	resp.tag = data.atom;
+	if (resp.tag == AtomContinue) {
+		if (*ptr == ' ') ptr++;
+		resp.text = ptr;
+		return resp;
+	}
 
 	data = parseData(imap);
 	if (data.type == Number) {