diff options
author | June McEnroe <june@causal.agency> | 2020-04-08 16:49:50 -0400 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2020-04-08 16:49:50 -0400 |
commit | dca3eb7a6a0c7e8a71d26c4390d908f5f6c2f32f (patch) | |
tree | dd82c828c185820ac7c39fc6db8681e1b5bbe649 /imap.h | |
parent | Simplify mboxrd output (diff) | |
download | imbox-dca3eb7a6a0c7e8a71d26c4390d908f5f6c2f32f.tar.gz imbox-dca3eb7a6a0c7e8a71d26c4390d908f5f6c2f32f.zip |
Use a real IMAP parser
Diffstat (limited to 'imap.h')
-rw-r--r-- | imap.h | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/imap.h b/imap.h new file mode 100644 index 0000000..0c9f6b9 --- /dev/null +++ b/imap.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2020 C. McEnroe <june@causal.agency> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <err.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sysexits.h> + +#define ENUM_ATOM \ + X(AtomNil, "NIL") \ + X(AtomOk, "OK") \ + X(AtomNo, "NO") \ + X(AtomBad, "BAD") \ + X(AtomPreauth, "PREAUTH") \ + X(AtomBye, "BYE") \ + X(AtomAlert, "ALERT") \ + X(AtomBadCharset, "BADCHARSET") \ + X(AtomCapability, "CAPABILITY") \ + X(AtomParse, "PARSE") \ + X(AtomPermanentFlags, "PERMANENTFLAGS") \ + X(AtomReadOnly, "READ-ONLY") \ + X(AtomReadWrite, "READ-WRITE") \ + X(AtomTryCreate, "TRYCREATE") \ + X(AtomUIDNext, "UIDNEXT") \ + X(AtomUIDValidity, "UIDVALIDITY") \ + X(AtomUnseen, "UNSEEN") \ + X(AtomList, "LIST") \ + X(AtomLSub, "LSUB") \ + X(AtomStatus, "STATUS") \ + X(AtomSearch, "SEARCH") \ + X(AtomFlags, "FLAGS") \ + X(AtomExists, "EXISTS") \ + X(AtomRecent, "RECENT") \ + X(AtomExpunge, "EXPUNGE") \ + X(AtomFetch, "FETCH") \ + X(AtomUntagged, "*") + +enum Atom { +#define X(id, str) id, + ENUM_ATOM +#undef X + AtomCap = 1024, +}; + +extern const char *Atoms[AtomCap]; + +static inline enum Atom atomn(const char *str, size_t len) { + enum Atom i; + for (i = 0; i < AtomCap; ++i) { + if (!Atoms[i]) break; + if (strlen(Atoms[i]) != len) continue; + if (!strncasecmp(Atoms[i], str, len)) return i; + } + if (i == AtomCap) errx(EX_SOFTWARE, "atom capacity exceeded"); + Atoms[i] = strndup(str, len); + if (!Atoms[i]) err(EX_OSERR, "strndup"); + return i; +} + +static inline enum Atom atom(const char *str) { + return atomn(str, strlen(str)); +} + +struct Data { + enum Type { + Atom, + Number, + String, + List, + } type; + union { + enum Atom atom; + uint32_t number; + char *string; + struct List { + size_t cap; + size_t len; + struct Data *ptr; + } list; + }; +}; + +static inline void dataFree(struct Data data) { + if (data.type == String) free(data.string); + if (data.type == List) { + for (size_t i = 0; i < data.list.len; ++i) { + dataFree(data.list.ptr[i]); + } + free(data.list.ptr); + } +} + +struct Resp { + enum Atom tag; + uint32_t number; + enum Atom resp; + struct List code; + struct List data; + const char *text; +}; + +static inline void respFree(struct Resp resp) { + for (size_t i = 0; i < resp.code.len; ++i) { + dataFree(resp.code.ptr[i]); + } + for (size_t i = 0; i < resp.data.len; ++i) { + dataFree(resp.data.ptr[i]); + } +} + +extern bool imapVerbose; +FILE *imapOpen(const char *host, const char *port); +struct Resp imapResp(FILE *imap); |