Blob


1 #include "a.h"
3 enum
4 {
5 BoxSubChunk = 16,
6 BoxChunk = 64,
7 MsgChunk = 256,
8 PartChunk = 4,
9 PartSubChunk = 4
10 };
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 void
87 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)
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;
117 return p;
120 void
121 partfree(Part *p)
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);
144 void
145 msgfree(Msg *m)
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);
157 void
158 msgplumb(Msg *m, int delete)
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];
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];
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];
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);
224 Msg*
225 msgcreate(Box *box)
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;
241 Msg*
242 msgbyimapuid(Box *box, uint uid, int docreate)
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;
260 Msg*
261 msgbyid(Box *box, uint id)
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;
274 Part*
275 partbyid(Msg *m, uint id)
277 if(m == nil)
278 return nil;
279 if(id >= m->npart)
280 return nil;
281 return m->part[id];
284 Part*
285 subpart(Part *p, uint a)
287 if(p == nil || a >= p->nsub)
288 return nil;
289 return p->sub[a];
292 void
293 hdrfree(Hdr *h)
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);
311 void
312 boxinit(void)
314 rootbox = emalloc(sizeof *rootbox);
315 rootbox->name = estrdup("");
316 rootbox->time = time(0);