blob: 202111f8e860c5c49904f5b355b83b5d3a370347 [file] [log] [blame]
#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; i<nboxes; i++)
if(boxes[i] && strcmp(boxes[i]->name, name) == 0)
return boxes[i];
return nil;
}
Box*
subbox(Box *b, char *elem)
{
int i;
for(i=0; i<b->nsub; 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; i<nboxes; i++)
if(boxes[i] && boxes[i]->id == 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; i<b->nmsg; 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; i<p->nsub; 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; i<m->npart; 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;
#ifdef PLAN9PORT
snprint(buf, sizeof buf, "Mail/%s/%ud", m->box->name, m->id);
#else
snprint(buf, sizeof buf, "/mail/fs/%s/%ud", m->box->name, m->id);
#endif
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; i<box->nmsg; 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; i<box->nmsg; 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);
}