From 128491a7281f03023f7271bbac3cfb9c83ebe535 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Thu, 9 Apr 2020 14:22:19 -0400 Subject: Send FETCH for uncached UIDs --- archive.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) (limited to 'archive.c') diff --git a/archive.c b/archive.c index 4facd57..f3c0059 100644 --- a/archive.c +++ b/archive.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -26,6 +27,53 @@ #define ENV_PASSWORD "BUBGER_IMAP_PASSWORD" +static const char *uidPath(uint32_t uid, const char *type) { + static char buf[PATH_MAX]; + snprintf(buf, sizeof(buf), "UID/%" PRIu32 ".%s", uid, type); + return buf; +} + +static void flatten(struct List *flat, struct List nested) { + for (size_t i = 0; i < nested.len; ++i) { + if (nested.ptr[i].type == List) { + flatten(flat, nested.ptr[i].list); + } else { + listPush(flat, nested.ptr[i]); + } + } +} + +static enum Atom fetchNew(FILE *imap, struct List threads) { + struct List uids = {0}; + flatten(&uids, threads); + for (size_t i = uids.len - 1; i < uids.len; --i) { + if (uids.ptr[i].type != Number) { + errx(EX_PROTOCOL, "invalid thread UID"); + } + uint32_t uid = uids.ptr[i].number; + int error = 0; + if (!error) error = access(uidPath(uid, "atom"), F_OK); + if (!error) error = access(uidPath(uid, "html"), F_OK); + if (!error) error = access(uidPath(uid, "mbox"), F_OK); + if (!error) { + uids.ptr[i] = uids.ptr[--uids.len]; + } + } + enum Atom tag = 0; + if (!uids.len) goto done; + + tag = atom("fetchNew"); + fprintf(imap, "%s UID FETCH ", Atoms[tag]); + for (size_t i = 0; i < uids.len; ++i) { + fprintf(imap, "%s%" PRIu32, (i ? "," : ""), uids.ptr[i].number); + } + fprintf(imap, " (UID ENVELOPE)\r\n"); + +done: + listFree(uids); + return tag; +} + static void checkValidity(uint32_t validity) { FILE *file = fopen("UIDVALIDITY", "r"); if (file) { @@ -101,7 +149,9 @@ int main(int argc, char *argv[]) { } enum Atom login = 0; - enum Atom examine = atom("examine"); + enum Atom examine = atom("EXAMINE"); + enum Atom thread = atom("THREAD"); + enum Atom export = 0; FILE *imap = imapOpen(host, port); for (struct Resp resp; resp = imapResp(imap), resp.resp != AtomBye;) { @@ -132,6 +182,22 @@ int main(int argc, char *argv[]) { } checkValidity(resp.code.ptr[1].number); } + + if (resp.tag == examine) { + fprintf( + imap, "%s UID THREAD %s UTF-8 %s\r\n", + Atoms[thread], algo, search + ); + } + + if (resp.resp == thread) { + if (!resp.data.len) { + errx(EX_TEMPFAIL, "no messages matching %s", search); + } + export = fetchNew(imap, resp.data); + } + + respFree(resp); } fclose(imap); } -- cgit 1.4.1