summaryrefslogtreecommitdiffstats
path: root/imap/fetchinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'imap/fetchinfo.c')
-rw-r--r--imap/fetchinfo.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/imap/fetchinfo.c b/imap/fetchinfo.c
new file mode 100644
index 0000000..96bd1e4
--- /dev/null
+++ b/imap/fetchinfo.c
@@ -0,0 +1,197 @@
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#ifndef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#include "imaptoken.h"
+#include "imapwrite.h"
+#include "fetchinfo.h"
+
+
+/* This file contains functions to parse a FETCH attribute list */
+
+static struct fetchinfo *alloc_headerlist(int);
+static char *good_section(char *);
+
+struct fetchinfo *fetchinfo_alloc(int oneonly)
+{
+struct fetchinfo *list, **listtail, *p;
+struct imaptoken *tok;
+
+ list=0;
+ listtail= &list;
+
+ while ((tok=currenttoken())->tokentype == IT_ATOM)
+ {
+ if (oneonly && list) break;
+ *listtail=p=(struct fetchinfo *)malloc(sizeof(*list));
+ if (!p) write_error_exit(0);
+ p->next=0;
+ p->name=my_strdup(tok->tokenbuf);
+ p->bodysection=0;
+ p->bodysublist=0;
+ p->ispartial=0;
+ listtail= &p->next;
+
+ if (strcmp(p->name, "ALL") == 0 ||
+ strcmp(p->name, "BODYSTRUCTURE") == 0 ||
+ strcmp(p->name, "ENVELOPE") == 0 ||
+ strcmp(p->name, "FLAGS") == 0 ||
+ strcmp(p->name, "FAST") == 0 ||
+ strcmp(p->name, "FULL") == 0 ||
+ strcmp(p->name, "INTERNALDATE") == 0 ||
+ strcmp(p->name, "RFC822") == 0 ||
+ strcmp(p->name, "RFC822.HEADER") == 0 ||
+ strcmp(p->name, "RFC822.SIZE") == 0 ||
+ strcmp(p->name, "RFC822.TEXT") == 0 ||
+ strcmp(p->name, "UID") == 0)
+ {
+ nexttoken();
+ continue;
+ }
+ if (strcmp(p->name, "BODY") && strcmp(p->name, "BODY.PEEK"))
+ break;
+ if (nexttoken()->tokentype != IT_LBRACKET) continue;
+
+ /* Parse BODY[ ... ] */
+
+ if ((tok=nexttoken())->tokentype != IT_RBRACKET)
+ {
+ char *s;
+
+ if ( (tok->tokentype != IT_ATOM &&
+ tok->tokentype != IT_NUMBER) ||
+ !(s=good_section(tok->tokenbuf)))
+ {
+ fetchinfo_free(list);
+ return (0);
+ }
+ p->bodysection=my_strdup(tok->tokenbuf);
+
+ if (strcmp(s, "HEADER.FIELDS") == 0 ||
+ strcmp(s, "HEADER.FIELDS.NOT") == 0)
+ {
+ /* Must be followed by header list */
+
+ if ((tok=nexttoken_nouc())->tokentype
+ != IT_LPAREN)
+ {
+ p->bodysublist=alloc_headerlist(1);
+ if (p->bodysublist == 0)
+ {
+ fetchinfo_free(list);
+ return (0);
+ }
+ }
+ else
+ {
+ nexttoken_nouc();
+ p->bodysublist=alloc_headerlist(0);
+ if ( currenttoken()->tokentype
+ != IT_RPAREN)
+ {
+ fetchinfo_free(list);
+ return (0);
+ }
+ }
+ }
+ tok=nexttoken();
+
+ }
+ else p->bodysection=my_strdup("");
+
+ if (tok->tokentype != IT_RBRACKET)
+ {
+ fetchinfo_free(list);
+ return (0);
+ }
+ tok=nexttoken();
+ if (tok->tokentype == IT_ATOM && tok->tokenbuf[0] == '<' &&
+ tok->tokenbuf[strlen(tok->tokenbuf)-1] == '>' &&
+ (p->ispartial=sscanf(tok->tokenbuf+1, "%lu.%lu",
+ &p->partialstart, &p->partialend)) > 0)
+ nexttoken();
+ }
+ return (list);
+}
+
+/* Just validate that the syntax of the attribute is correct */
+
+static char *good_section(char *p)
+{
+int has_mime=0;
+
+ while (isdigit((int)(unsigned char)*p))
+ {
+ if (*p == '0') return (0);
+ has_mime=1;
+ while (isdigit((int)(unsigned char)*p)) ++p;
+ if (*p == '\0')
+ return (p);
+
+ if (*p != '.') return (0);
+ ++p;
+ }
+
+ if (strcmp(p, "HEADER") == 0 ||
+ strcmp(p, "HEADER.FIELDS") == 0 ||
+ strcmp(p, "HEADER.FIELDS.NOT") == 0 ||
+ strcmp(p, "TEXT") == 0)
+ return (p);
+
+ if (strcmp(p, "MIME") == 0 && has_mime) return (p);
+ return (0);
+}
+
+/* Header list looks like atoms to me */
+
+static struct fetchinfo *alloc_headerlist(int oneonly)
+{
+struct fetchinfo *list, **listtail, *p;
+struct imaptoken *tok;
+
+ list=0;
+ listtail= &list;
+
+ while ((tok=currenttoken())->tokentype == IT_ATOM ||
+ tok->tokentype == IT_QUOTED_STRING ||
+ tok->tokentype == IT_NUMBER)
+ {
+ *listtail=p=(struct fetchinfo *)malloc(sizeof(*list));
+ if (!p) write_error_exit(0);
+ p->next=0;
+ p->name=my_strdup(tok->tokenbuf);
+ p->bodysublist=0;
+ p->bodysection=0;
+ listtail= &p->next;
+ if (oneonly)
+ break;
+ nexttoken_nouc();
+ }
+ return (list);
+}
+
+void fetchinfo_free(struct fetchinfo *p)
+{
+struct fetchinfo *q;
+
+ while (p)
+ {
+ if (p->bodysublist) fetchinfo_free(p->bodysublist);
+ q=p->next;
+ if (p->name) free(p->name);
+ if (p->bodysection) free(p->bodysection);
+ free(p);
+ p=q;
+ }
+}