From 22fdd37cd722f35625ad4ff03baa9f218a0c1090 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Thu, 9 Apr 2020 12:28:08 -0400 Subject: Add IMAP parser --- imap.h | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 imap.h (limited to 'imap.h') 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 + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +#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); -- cgit 1.4.1