Blob
1 #include "a.h"3 enum4 {5 BoxSubChunk = 16,6 BoxChunk = 64,7 MsgChunk = 256,8 PartChunk = 4,9 PartSubChunk = 410 };12 Box **boxes;13 uint nboxes;14 Box *rootbox;15 int boxid;17 Box*18 boxbyname(char *name)19 {20 int i;22 /* LATER: replace with hash table */23 for(i=0; i<nboxes; i++)24 if(boxes[i] && strcmp(boxes[i]->name, name) == 0)25 return boxes[i];26 return nil;27 }29 Box*30 subbox(Box *b, char *elem)31 {32 int i;34 for(i=0; i<b->nsub; i++)35 if(b->sub[i] && strcmp(b->sub[i]->elem, elem) == 0)36 return b->sub[i];37 return nil;38 }40 Box*41 boxbyid(uint id)42 {43 int i;45 /* LATER: replace with binary search */46 for(i=0; i<nboxes; i++)47 if(boxes[i] && boxes[i]->id == id)48 return boxes[i];49 return nil;50 }52 Box*53 boxcreate(char *name)54 {55 char *p;56 Box *b, *bb;58 if((b = boxbyname(name)) != nil)59 return b;61 b = emalloc(sizeof *b);62 b->id = ++boxid;63 b->time = time(0);64 b->name = estrdup(name);65 b->uidnext = 1;66 p = strrchr(b->name, '/');67 if(p){68 *p = 0;69 bb = boxcreate(b->name);70 *p = '/';71 b->elem = p+1;72 }else{73 bb = rootbox;74 b->elem = b->name;75 }76 if(nboxes%BoxChunk == 0)77 boxes = erealloc(boxes, (nboxes+BoxChunk)*sizeof boxes[0]);78 boxes[nboxes++] = b;79 if(bb->nsub%BoxSubChunk == 0)80 bb->sub = erealloc(bb->sub, (bb->nsub+BoxSubChunk)*sizeof bb->sub[0]);81 bb->sub[bb->nsub++] = b;82 b->parent = bb;83 return b;84 }86 void87 boxfree(Box *b)88 {89 int i;91 if(b == nil)92 return;93 for(i=0; i<b->nmsg; i++)94 msgfree(b->msg[i]);95 free(b->msg);96 free(b);97 }99 Part*100 partcreate(Msg *m, Part *pp)101 {102 Part *p;104 if(m->npart%PartChunk == 0)105 m->part = erealloc(m->part, (m->npart+PartChunk)*sizeof m->part[0]);106 p = emalloc(sizeof *p);107 p->msg = m;108 p->ix = m->npart;109 m->part[m->npart++] = p;110 if(pp){111 if(pp->nsub%PartSubChunk == 0)112 pp->sub = erealloc(pp->sub, (pp->nsub+PartSubChunk)*sizeof pp->sub[0]);113 p->pix = pp->nsub;114 p->parent = pp;115 pp->sub[pp->nsub++] = p;116 }117 return p;118 }120 void121 partfree(Part *p)122 {123 int i;125 if(p == nil)126 return;127 for(i=0; i<p->nsub; i++)128 partfree(p->sub[i]);129 free(p->sub);130 hdrfree(p->hdr);131 free(p->type);132 free(p->idstr);133 free(p->desc);134 free(p->encoding);135 free(p->charset);136 free(p->raw);137 free(p->rawheader);138 free(p->rawbody);139 free(p->mimeheader);140 free(p->body);141 free(p);142 }144 void145 msgfree(Msg *m)146 {147 int i;149 if(m == nil)150 return;151 for(i=0; i<m->npart; i++)152 free(m->part[i]);153 free(m->part);154 free(m);155 }157 void158 msgplumb(Msg *m, int delete)159 {160 static int fd = -1;161 Plumbmsg p;162 Plumbattr a[10];163 char buf[256], date[40];164 int ai;166 if(m == nil || m->npart < 1 || m->part[0]->hdr == nil)167 return;168 if(m->box && strcmp(m->box->name, "mbox") != 0)169 return;171 p.src = "mailfs";172 p.dst = "seemail";173 p.wdir = "/";174 p.type = "text";176 ai = 0;177 a[ai].name = "filetype";178 a[ai].value = "mail";180 a[++ai].name = "mailtype";181 a[ai].value = delete?"delete":"new";182 a[ai-1].next = &a[ai];184 if(m->part[0]->hdr->from){185 a[++ai].name = "sender";186 a[ai].value = m->part[0]->hdr->from;187 a[ai-1].next = &a[ai];188 }190 if(m->part[0]->hdr->subject){191 a[++ai].name = "subject";192 a[ai].value = m->part[0]->hdr->subject;193 a[ai-1].next = &a[ai];194 }196 if(m->part[0]->hdr->digest){197 a[++ai].name = "digest";198 a[ai].value = m->part[0]->hdr->digest;199 a[ai-1].next = &a[ai];200 }202 strcpy(date, ctime(m->date));203 date[strlen(date)-1] = 0; /* newline */204 a[++ai].name = "date";205 a[ai].value = date;206 a[ai-1].next = &a[ai];208 a[ai].next = nil;210 p.attr = a;211 snprint(buf, sizeof buf, "Mail/%s/%ud", m->box->name, m->id);212 p.ndata = strlen(buf);213 p.data = buf;215 if(fd < 0)216 fd = plumbopen("send", OWRITE);217 if(fd < 0)218 return;220 plumbsend(fd, &p);221 }224 Msg*225 msgcreate(Box *box)226 {227 Msg *m;229 m = emalloc(sizeof *m);230 m->box = box;231 partcreate(m, nil);232 m->part[0]->type = estrdup("message/rfc822");233 if(box->nmsg%MsgChunk == 0)234 box->msg = erealloc(box->msg, (box->nmsg+MsgChunk)*sizeof box->msg[0]);235 m->ix = box->nmsg++;236 box->msg[m->ix] = m;237 m->id = ++box->msgid;238 return m;239 }241 Msg*242 msgbyimapuid(Box *box, uint uid, int docreate)243 {244 int i;245 Msg *msg;247 if(box == nil)248 return nil;249 /* LATER: binary search or something */250 for(i=0; i<box->nmsg; i++)251 if(box->msg[i]->imapuid == uid)252 return box->msg[i];253 if(!docreate)254 return nil;255 msg = msgcreate(box);256 msg->imapuid = uid;257 return msg;258 }260 Msg*261 msgbyid(Box *box, uint id)262 {263 int i;265 if(box == nil)266 return nil;267 /* LATER: binary search or something */268 for(i=0; i<box->nmsg; i++)269 if(box->msg[i]->id == id)270 return box->msg[i];271 return nil;272 }274 Part*275 partbyid(Msg *m, uint id)276 {277 if(m == nil)278 return nil;279 if(id >= m->npart)280 return nil;281 return m->part[id];282 }284 Part*285 subpart(Part *p, uint a)286 {287 if(p == nil || a >= p->nsub)288 return nil;289 return p->sub[a];290 }292 void293 hdrfree(Hdr *h)294 {295 if(h == nil)296 return;297 free(h->date);298 free(h->subject);299 free(h->from);300 free(h->sender);301 free(h->replyto);302 free(h->to);303 free(h->cc);304 free(h->bcc);305 free(h->inreplyto);306 free(h->messageid);307 free(h->digest);308 free(h);309 }311 void312 boxinit(void)313 {314 rootbox = emalloc(sizeof *rootbox);315 rootbox->name = estrdup("");316 rootbox->time = time(0);317 }