#include "a.h" enum { BoxSubChunk = 16, BoxChunk = 64, MsgChunk = 256, PartChunk = 4, PartSubChunk = 4 }; Box **boxes; uint nboxes; Box *rootbox; int boxid; Box* boxbyname(char *name) { int i; /* LATER: replace with hash table */ for(i=0; iname, name) == 0) return boxes[i]; return nil; } Box* subbox(Box *b, char *elem) { int i; for(i=0; insub; i++) if(b->sub[i] && strcmp(b->sub[i]->elem, elem) == 0) return b->sub[i]; return nil; } Box* boxbyid(uint id) { int i; /* LATER: replace with binary search */ for(i=0; iid == id) return boxes[i]; return nil; } Box* boxcreate(char *name) { char *p; Box *b, *bb; if((b = boxbyname(name)) != nil) return b; b = emalloc(sizeof *b); b->id = ++boxid; b->time = time(0); b->name = estrdup(name); b->uidnext = 1; p = strrchr(b->name, '/'); if(p){ *p = 0; bb = boxcreate(b->name); *p = '/'; b->elem = p+1; }else{ bb = rootbox; b->elem = b->name; } if(nboxes%BoxChunk == 0) boxes = erealloc(boxes, (nboxes+BoxChunk)*sizeof boxes[0]); boxes[nboxes++] = b; if(bb->nsub%BoxSubChunk == 0) bb->sub = erealloc(bb->sub, (bb->nsub+BoxSubChunk)*sizeof bb->sub[0]); bb->sub[bb->nsub++] = b; b->parent = bb; return b; } void boxfree(Box *b) { int i; if(b == nil) return; for(i=0; inmsg; i++) msgfree(b->msg[i]); free(b->msg); free(b); } Part* partcreate(Msg *m, Part *pp) { Part *p; if(m->npart%PartChunk == 0) m->part = erealloc(m->part, (m->npart+PartChunk)*sizeof m->part[0]); p = emalloc(sizeof *p); p->msg = m; p->ix = m->npart; m->part[m->npart++] = p; if(pp){ if(pp->nsub%PartSubChunk == 0) pp->sub = erealloc(pp->sub, (pp->nsub+PartSubChunk)*sizeof pp->sub[0]); p->pix = pp->nsub; p->parent = pp; pp->sub[pp->nsub++] = p; } return p; } void partfree(Part *p) { int i; if(p == nil) return; for(i=0; insub; i++) partfree(p->sub[i]); free(p->sub); hdrfree(p->hdr); free(p->type); free(p->idstr); free(p->desc); free(p->encoding); free(p->charset); free(p->raw); free(p->rawheader); free(p->rawbody); free(p->mimeheader); free(p->body); free(p); } void msgfree(Msg *m) { int i; if(m == nil) return; for(i=0; inpart; i++) free(m->part[i]); free(m->part); free(m); } void msgplumb(Msg *m, int delete) { static int fd = -1; Plumbmsg p; Plumbattr a[10]; char buf[256], date[40]; int ai; if(m == nil || m->npart < 1 || m->part[0]->hdr == nil) return; if(m->box && strcmp(m->box->name, "mbox") != 0) return; p.src = "mailfs"; p.dst = "seemail"; p.wdir = "/"; p.type = "text"; ai = 0; a[ai].name = "filetype"; a[ai].value = "mail"; a[++ai].name = "mailtype"; a[ai].value = delete?"delete":"new"; a[ai-1].next = &a[ai]; if(m->part[0]->hdr->from){ a[++ai].name = "sender"; a[ai].value = m->part[0]->hdr->from; a[ai-1].next = &a[ai]; } if(m->part[0]->hdr->subject){ a[++ai].name = "subject"; a[ai].value = m->part[0]->hdr->subject; a[ai-1].next = &a[ai]; } if(m->part[0]->hdr->digest){ a[++ai].name = "digest"; a[ai].value = m->part[0]->hdr->digest; a[ai-1].next = &a[ai]; } strcpy(date, ctime(m->date)); date[strlen(date)-1] = 0; /* newline */ a[++ai].name = "date"; a[ai].value = date; a[ai-1].next = &a[ai]; a[ai].next = nil; p.attr = a; snprint(buf, sizeof buf, "Mail/%s/%ud", m->box->name, m->id); p.ndata = strlen(buf); p.data = buf; if(fd < 0) fd = plumbopen("send", OWRITE); if(fd < 0) return; plumbsend(fd, &p); } Msg* msgcreate(Box *box) { Msg *m; m = emalloc(sizeof *m); m->box = box; partcreate(m, nil); m->part[0]->type = estrdup("message/rfc822"); if(box->nmsg%MsgChunk == 0) box->msg = erealloc(box->msg, (box->nmsg+MsgChunk)*sizeof box->msg[0]); m->ix = box->nmsg++; box->msg[m->ix] = m; m->id = ++box->msgid; return m; } Msg* msgbyimapuid(Box *box, uint uid, int docreate) { int i; Msg *msg; if(box == nil) return nil; /* LATER: binary search or something */ for(i=0; inmsg; i++) if(box->msg[i]->imapuid == uid) return box->msg[i]; if(!docreate) return nil; msg = msgcreate(box); msg->imapuid = uid; return msg; } Msg* msgbyid(Box *box, uint id) { int i; if(box == nil) return nil; /* LATER: binary search or something */ for(i=0; inmsg; i++) if(box->msg[i]->id == id) return box->msg[i]; return nil; } Part* partbyid(Msg *m, uint id) { if(m == nil) return nil; if(id >= m->npart) return nil; return m->part[id]; } Part* subpart(Part *p, uint a) { if(p == nil || a >= p->nsub) return nil; return p->sub[a]; } void hdrfree(Hdr *h) { if(h == nil) return; free(h->date); free(h->subject); free(h->from); free(h->sender); free(h->replyto); free(h->to); free(h->cc); free(h->bcc); free(h->inreplyto); free(h->messageid); free(h->digest); free(h); } void boxinit(void) { rootbox = emalloc(sizeof *rootbox); rootbox->name = estrdup(""); rootbox->time = time(0); }