EXPORTED int dlist_parse_asatomlist(struct dlist **dlp, int parsekey, struct protstream *in) { int c = dlist_parse(dlp, parsekey, in, NULL); /* make a list with one item */ if (*dlp && !dlist_isatomlist(*dlp)) { struct dlist *tmp = dlist_newlist(NULL, ""); dlist_stitch(tmp, *dlp); *dlp = tmp; } return c; }
HIDDEN int parse_backup_line(struct protstream *in, time_t *ts, struct buf *cmd, struct dlist **kin) { struct dlist *dl = NULL; struct buf buf = BUF_INITIALIZER; int64_t t; int c; c = prot_getc(in); if (c == '#') eatline(in, c); else prot_ungetc(c, in); c = getint64(in, &t); if (c == EOF) goto fail; c = getword(in, &buf); if (c == EOF) goto fail; c = dlist_parse(&dl, /*parsekeys*/ 1, 1, in); if (!dl) { fprintf(stderr, "\ndidn't parse dlist, error %i\n", c); goto fail; } if (c == '\r') c = prot_getc(in); if (c != '\n') { fprintf(stderr, "expected newline, got '%c'\n", c); eatline(in, c); goto fail; } if (kin) *kin = dl; if (cmd) buf_copy(cmd, &buf); if (ts) *ts = (time_t) t; buf_free(&buf); return c; fail: if (dl) dlist_free(&dl); buf_free(&buf); return c; }
EXPORTED int dlist_parsemap(struct dlist **dlp, int parsekey, const char *base, unsigned len) { struct protstream *stream; int c; struct dlist *dl = NULL; stream = prot_readmap(base, len); prot_setisclient(stream, 1); /* don't sync literals */ c = dlist_parse(&dl, parsekey, stream, NULL); prot_free(stream); if (c != EOF) { dlist_free(&dl); return IMAP_IOERROR; /* failed to slurp entire buffer */ } *dlp = dl; return 0; }
EXPORTED int dlist_parse(struct dlist **dlp, int parsekey, struct protstream *in, const char *alt_reserve_base) { struct dlist *dl = NULL; static struct buf kbuf; static struct buf vbuf; int c; /* handle the key if wanted */ if (parsekey) { c = getastring(in, NULL, &kbuf); c = next_nonspace(in, c); } else { buf_setcstr(&kbuf, ""); c = prot_getc(in); } /* connection dropped? */ if (c == EOF) goto fail; /* check what sort of value we have */ if (c == '(') { dl = dlist_newlist(NULL, kbuf.s); c = next_nonspace(in, ' '); while (c != ')') { struct dlist *di = NULL; prot_ungetc(c, in); c = dlist_parse(&di, 0, in, alt_reserve_base); if (di) dlist_stitch(dl, di); c = next_nonspace(in, c); if (c == EOF) goto fail; } c = prot_getc(in); } else if (c == '%') { /* no whitespace allowed here */ c = prot_getc(in); if (c == '(') { dl = dlist_newkvlist(NULL, kbuf.s); c = next_nonspace(in, ' '); while (c != ')') { struct dlist *di = NULL; prot_ungetc(c, in); c = dlist_parse(&di, 1, in, alt_reserve_base); if (di) dlist_stitch(dl, di); c = next_nonspace(in, c); if (c == EOF) goto fail; } } else if (c == '{') { struct message_guid tmp_guid; static struct buf pbuf, gbuf; unsigned size = 0; const char *fname; const char *part; c = getastring(in, NULL, &pbuf); if (c != ' ') goto fail; c = getastring(in, NULL, &gbuf); if (c != ' ') goto fail; c = getuint32(in, &size); if (c != '}') goto fail; c = prot_getc(in); if (c == '\r') c = prot_getc(in); if (c != '\n') goto fail; if (!message_guid_decode(&tmp_guid, gbuf.s)) goto fail; part = alt_reserve_base ? alt_reserve_base : pbuf.s; if (reservefile(in, part, &tmp_guid, size, &fname)) goto fail; dl = dlist_setfile(NULL, kbuf.s, pbuf.s, &tmp_guid, size, fname); /* file literal */ } else { /* unknown percent type */ goto fail; } c = prot_getc(in); } else if (c == '{') { prot_ungetc(c, in); /* could be binary in a literal */ c = getbastring(in, NULL, &vbuf); dl = dlist_setmap(NULL, kbuf.s, vbuf.s, vbuf.len); } else if (c == '\\') { /* special case for flags */ prot_ungetc(c, in); c = getastring(in, NULL, &vbuf); dl = dlist_setflag(NULL, kbuf.s, vbuf.s); } else { prot_ungetc(c, in); c = getnastring(in, NULL, &vbuf); dl = dlist_setatom(NULL, kbuf.s, vbuf.s); } /* success */ *dlp = dl; return c; fail: dlist_free(&dl); return EOF; }