17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
49a747e4fSDavid du Colombier #include <auth.h>
57dd7cddfSDavid du Colombier #include "imap4d.h"
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier char *fetchPartNames[FPMax] =
87dd7cddfSDavid du Colombier {
97dd7cddfSDavid du Colombier "",
107dd7cddfSDavid du Colombier "HEADER",
117dd7cddfSDavid du Colombier "HEADER.FIELDS",
127dd7cddfSDavid du Colombier "HEADER.FIELDS.NOT",
137dd7cddfSDavid du Colombier "MIME",
147dd7cddfSDavid du Colombier "TEXT",
157dd7cddfSDavid du Colombier };
167dd7cddfSDavid du Colombier
177dd7cddfSDavid du Colombier /*
187dd7cddfSDavid du Colombier * implicitly set the \seen flag. done in a separate pass
197dd7cddfSDavid du Colombier * so the .imp file doesn't need to be open while the
207dd7cddfSDavid du Colombier * messages are sent to the client.
217dd7cddfSDavid du Colombier */
227dd7cddfSDavid du Colombier int
fetchSeen(Box * box,Msg * m,int uids,void * vf)237dd7cddfSDavid du Colombier fetchSeen(Box *box, Msg *m, int uids, void *vf)
247dd7cddfSDavid du Colombier {
257dd7cddfSDavid du Colombier Fetch *f;
267dd7cddfSDavid du Colombier
277dd7cddfSDavid du Colombier USED(uids);
287dd7cddfSDavid du Colombier
297dd7cddfSDavid du Colombier if(m->expunged)
307dd7cddfSDavid du Colombier return uids;
317dd7cddfSDavid du Colombier for(f = vf; f != nil; f = f->next){
327dd7cddfSDavid du Colombier switch(f->op){
337dd7cddfSDavid du Colombier case FRfc822:
347dd7cddfSDavid du Colombier case FRfc822Text:
357dd7cddfSDavid du Colombier case FBodySect:
367dd7cddfSDavid du Colombier msgSeen(box, m);
377dd7cddfSDavid du Colombier goto breakout;
387dd7cddfSDavid du Colombier }
397dd7cddfSDavid du Colombier }
407dd7cddfSDavid du Colombier breakout:
417dd7cddfSDavid du Colombier
427dd7cddfSDavid du Colombier return 1;
437dd7cddfSDavid du Colombier }
447dd7cddfSDavid du Colombier
457dd7cddfSDavid du Colombier /*
467dd7cddfSDavid du Colombier * fetch messages
477dd7cddfSDavid du Colombier *
487dd7cddfSDavid du Colombier * imap4 body[] requestes get translated to upas/fs files as follows
497dd7cddfSDavid du Colombier * body[id.header] == id/rawheader file + extra \r\n
507dd7cddfSDavid du Colombier * body[id.text] == id/rawbody
517dd7cddfSDavid du Colombier * body[id.mime] == id/mimeheader + extra \r\n
527dd7cddfSDavid du Colombier * body[id] === body[id.header] + body[id.text]
537dd7cddfSDavid du Colombier */
547dd7cddfSDavid du Colombier int
fetchMsg(Box *,Msg * m,int uids,void * vf)55becaf2abSDavid du Colombier fetchMsg(Box *, Msg *m, int uids, void *vf)
567dd7cddfSDavid du Colombier {
577dd7cddfSDavid du Colombier Tm tm;
587dd7cddfSDavid du Colombier Fetch *f;
597dd7cddfSDavid du Colombier char *sep;
607dd7cddfSDavid du Colombier int todo;
617dd7cddfSDavid du Colombier
627dd7cddfSDavid du Colombier if(m->expunged)
637dd7cddfSDavid du Colombier return uids;
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier todo = 0;
667dd7cddfSDavid du Colombier for(f = vf; f != nil; f = f->next){
677dd7cddfSDavid du Colombier switch(f->op){
687dd7cddfSDavid du Colombier case FFlags:
69229d2d34SDavid du Colombier todo = 1;
707dd7cddfSDavid du Colombier break;
717dd7cddfSDavid du Colombier case FUid:
727dd7cddfSDavid du Colombier todo = 1;
737dd7cddfSDavid du Colombier break;
747dd7cddfSDavid du Colombier case FInternalDate:
757dd7cddfSDavid du Colombier case FEnvelope:
767dd7cddfSDavid du Colombier case FRfc822:
777dd7cddfSDavid du Colombier case FRfc822Head:
787dd7cddfSDavid du Colombier case FRfc822Size:
797dd7cddfSDavid du Colombier case FRfc822Text:
807dd7cddfSDavid du Colombier case FBodySect:
817dd7cddfSDavid du Colombier case FBodyPeek:
827dd7cddfSDavid du Colombier case FBody:
837dd7cddfSDavid du Colombier case FBodyStruct:
847dd7cddfSDavid du Colombier todo = 1;
857dd7cddfSDavid du Colombier if(!msgStruct(m, 1)){
867dd7cddfSDavid du Colombier msgDead(m);
877dd7cddfSDavid du Colombier return uids;
887dd7cddfSDavid du Colombier }
897dd7cddfSDavid du Colombier break;
907dd7cddfSDavid du Colombier default:
917dd7cddfSDavid du Colombier bye("bad implementation of fetch");
927dd7cddfSDavid du Colombier return 0;
937dd7cddfSDavid du Colombier }
947dd7cddfSDavid du Colombier }
957dd7cddfSDavid du Colombier
967dd7cddfSDavid du Colombier if(m->expunged)
977dd7cddfSDavid du Colombier return uids;
987dd7cddfSDavid du Colombier if(!todo)
997dd7cddfSDavid du Colombier return 1;
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier /*
1027dd7cddfSDavid du Colombier * note: it is allowed to send back the responses one at a time
1037dd7cddfSDavid du Colombier * rather than all together. this is exploited to send flags elsewhere.
1047dd7cddfSDavid du Colombier */
105f121929fSDavid du Colombier Bprint(&bout, "* %lud FETCH (", m->seq);
1067dd7cddfSDavid du Colombier sep = "";
1077dd7cddfSDavid du Colombier if(uids){
108*40fe8d0dSDavid du Colombier Bprint(&bout, "UID %lud", m->uid);
1097dd7cddfSDavid du Colombier sep = " ";
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier for(f = vf; f != nil; f = f->next){
1127dd7cddfSDavid du Colombier switch(f->op){
1137dd7cddfSDavid du Colombier default:
1147dd7cddfSDavid du Colombier bye("bad implementation of fetch");
1157dd7cddfSDavid du Colombier break;
1167dd7cddfSDavid du Colombier case FFlags:
117*40fe8d0dSDavid du Colombier Bprint(&bout, "%sFLAGS (", sep);
118becaf2abSDavid du Colombier writeFlags(&bout, m, 1);
119becaf2abSDavid du Colombier Bprint(&bout, ")");
120becaf2abSDavid du Colombier break;
1217dd7cddfSDavid du Colombier case FUid:
1227dd7cddfSDavid du Colombier if(uids)
1237dd7cddfSDavid du Colombier continue;
124*40fe8d0dSDavid du Colombier Bprint(&bout, "%sUID %lud", sep, m->uid);
1257dd7cddfSDavid du Colombier break;
1267dd7cddfSDavid du Colombier case FEnvelope:
127*40fe8d0dSDavid du Colombier Bprint(&bout, "%sENVELOPE ", sep);
1287dd7cddfSDavid du Colombier fetchEnvelope(m);
1297dd7cddfSDavid du Colombier break;
1307dd7cddfSDavid du Colombier case FInternalDate:
131*40fe8d0dSDavid du Colombier Bprint(&bout, "%sINTERNALDATE ", sep);
1327dd7cddfSDavid du Colombier Bimapdate(&bout, date2tm(&tm, m->unixDate));
1337dd7cddfSDavid du Colombier break;
1347dd7cddfSDavid du Colombier case FBody:
135*40fe8d0dSDavid du Colombier Bprint(&bout, "%sBODY ", sep);
1367dd7cddfSDavid du Colombier fetchBodyStruct(m, &m->head, 0);
1377dd7cddfSDavid du Colombier break;
1387dd7cddfSDavid du Colombier case FBodyStruct:
139*40fe8d0dSDavid du Colombier Bprint(&bout, "%sBODYSTRUCTURE ", sep);
1407dd7cddfSDavid du Colombier fetchBodyStruct(m, &m->head, 1);
1417dd7cddfSDavid du Colombier break;
1427dd7cddfSDavid du Colombier case FRfc822Size:
143f121929fSDavid du Colombier Bprint(&bout, "%sRFC822.SIZE %lud", sep, msgSize(m));
1447dd7cddfSDavid du Colombier break;
1457dd7cddfSDavid du Colombier case FRfc822:
1467dd7cddfSDavid du Colombier f->part = FPAll;
147f121929fSDavid du Colombier Bprint(&bout, "%sRFC822", sep);
1487dd7cddfSDavid du Colombier fetchBody(m, f);
1497dd7cddfSDavid du Colombier break;
1507dd7cddfSDavid du Colombier case FRfc822Head:
1517dd7cddfSDavid du Colombier f->part = FPHead;
152*40fe8d0dSDavid du Colombier Bprint(&bout, "%sRFC822.HEADER", sep);
1537dd7cddfSDavid du Colombier fetchBody(m, f);
1547dd7cddfSDavid du Colombier break;
1557dd7cddfSDavid du Colombier case FRfc822Text:
1567dd7cddfSDavid du Colombier f->part = FPText;
157*40fe8d0dSDavid du Colombier Bprint(&bout, "%sRFC822.TEXT", sep);
1587dd7cddfSDavid du Colombier fetchBody(m, f);
1597dd7cddfSDavid du Colombier break;
1607dd7cddfSDavid du Colombier case FBodySect:
1617dd7cddfSDavid du Colombier case FBodyPeek:
162*40fe8d0dSDavid du Colombier Bprint(&bout, "%sBODY", sep);
1637dd7cddfSDavid du Colombier fetchBody(fetchSect(m, f), f);
1647dd7cddfSDavid du Colombier break;
1657dd7cddfSDavid du Colombier }
1667dd7cddfSDavid du Colombier sep = " ";
1677dd7cddfSDavid du Colombier }
1687dd7cddfSDavid du Colombier Bprint(&bout, ")\r\n");
1697dd7cddfSDavid du Colombier
1707dd7cddfSDavid du Colombier return 1;
1717dd7cddfSDavid du Colombier }
1727dd7cddfSDavid du Colombier
1737dd7cddfSDavid du Colombier /*
1747dd7cddfSDavid du Colombier * print out section, part, headers;
1757dd7cddfSDavid du Colombier * find and return message section
1767dd7cddfSDavid du Colombier */
1777dd7cddfSDavid du Colombier Msg *
fetchSect(Msg * m,Fetch * f)1787dd7cddfSDavid du Colombier fetchSect(Msg *m, Fetch *f)
1797dd7cddfSDavid du Colombier {
1807dd7cddfSDavid du Colombier Bputc(&bout, '[');
1817dd7cddfSDavid du Colombier BNList(&bout, f->sect, ".");
1827dd7cddfSDavid du Colombier if(f->part != FPAll){
1837dd7cddfSDavid du Colombier if(f->sect != nil)
1847dd7cddfSDavid du Colombier Bputc(&bout, '.');
1857dd7cddfSDavid du Colombier Bprint(&bout, "%s", fetchPartNames[f->part]);
1867dd7cddfSDavid du Colombier if(f->hdrs != nil){
1877dd7cddfSDavid du Colombier Bprint(&bout, " (");
1887dd7cddfSDavid du Colombier BSList(&bout, f->hdrs, " ");
1897dd7cddfSDavid du Colombier Bputc(&bout, ')');
1907dd7cddfSDavid du Colombier }
1917dd7cddfSDavid du Colombier }
1927dd7cddfSDavid du Colombier Bprint(&bout, "]");
1937dd7cddfSDavid du Colombier return findMsgSect(m, f->sect);
1947dd7cddfSDavid du Colombier }
1957dd7cddfSDavid du Colombier
1967dd7cddfSDavid du Colombier /*
1977dd7cddfSDavid du Colombier * actually return the body pieces
1987dd7cddfSDavid du Colombier */
1997dd7cddfSDavid du Colombier void
fetchBody(Msg * m,Fetch * f)2007dd7cddfSDavid du Colombier fetchBody(Msg *m, Fetch *f)
2017dd7cddfSDavid du Colombier {
2027dd7cddfSDavid du Colombier Pair p;
2037dd7cddfSDavid du Colombier char *s, *t, *e, buf[BufSize + 2];
2047dd7cddfSDavid du Colombier ulong n, start, stop, pos;
2057dd7cddfSDavid du Colombier int fd, nn;
2067dd7cddfSDavid du Colombier
2077dd7cddfSDavid du Colombier if(m == nil){
2087dd7cddfSDavid du Colombier fetchBodyStr(f, "", 0);
2097dd7cddfSDavid du Colombier return;
2107dd7cddfSDavid du Colombier }
2117dd7cddfSDavid du Colombier switch(f->part){
2127dd7cddfSDavid du Colombier case FPHeadFields:
2137dd7cddfSDavid du Colombier case FPHeadFieldsNot:
2147dd7cddfSDavid du Colombier n = m->head.size + 3;
2157dd7cddfSDavid du Colombier s = emalloc(n);
2167dd7cddfSDavid du Colombier n = selectFields(s, n, m->head.buf, f->hdrs, f->part == FPHeadFields);
2177dd7cddfSDavid du Colombier fetchBodyStr(f, s, n);
2187dd7cddfSDavid du Colombier free(s);
2197dd7cddfSDavid du Colombier return;
2207dd7cddfSDavid du Colombier case FPHead:
2217dd7cddfSDavid du Colombier fetchBodyStr(f, m->head.buf, m->head.size);
2227dd7cddfSDavid du Colombier return;
2237dd7cddfSDavid du Colombier case FPMime:
2247dd7cddfSDavid du Colombier fetchBodyStr(f, m->mime.buf, m->mime.size);
2257dd7cddfSDavid du Colombier return;
2267dd7cddfSDavid du Colombier case FPAll:
2277dd7cddfSDavid du Colombier fd = msgFile(m, "rawbody");
2287dd7cddfSDavid du Colombier if(fd < 0){
2297dd7cddfSDavid du Colombier msgDead(m);
2307dd7cddfSDavid du Colombier fetchBodyStr(f, "", 0);
2317dd7cddfSDavid du Colombier return;
2327dd7cddfSDavid du Colombier }
2337dd7cddfSDavid du Colombier p = fetchBodyPart(f, msgSize(m));
2347dd7cddfSDavid du Colombier start = p.start;
2357dd7cddfSDavid du Colombier if(start < m->head.size){
2367dd7cddfSDavid du Colombier stop = p.stop;
2377dd7cddfSDavid du Colombier if(stop > m->head.size)
2387dd7cddfSDavid du Colombier stop = m->head.size;
2397dd7cddfSDavid du Colombier Bwrite(&bout, &m->head.buf[start], stop - start);
2407dd7cddfSDavid du Colombier start = 0;
2417dd7cddfSDavid du Colombier stop = p.stop;
2427dd7cddfSDavid du Colombier if(stop <= m->head.size){
2437dd7cddfSDavid du Colombier close(fd);
2447dd7cddfSDavid du Colombier return;
2457dd7cddfSDavid du Colombier }
2467dd7cddfSDavid du Colombier }else
2477dd7cddfSDavid du Colombier start -= m->head.size;
2487dd7cddfSDavid du Colombier stop = p.stop - m->head.size;
2497dd7cddfSDavid du Colombier break;
2507dd7cddfSDavid du Colombier case FPText:
2517dd7cddfSDavid du Colombier fd = msgFile(m, "rawbody");
2527dd7cddfSDavid du Colombier if(fd < 0){
2537dd7cddfSDavid du Colombier msgDead(m);
2547dd7cddfSDavid du Colombier fetchBodyStr(f, "", 0);
2557dd7cddfSDavid du Colombier return;
2567dd7cddfSDavid du Colombier }
2577dd7cddfSDavid du Colombier p = fetchBodyPart(f, m->size);
2587dd7cddfSDavid du Colombier start = p.start;
2597dd7cddfSDavid du Colombier stop = p.stop;
2607dd7cddfSDavid du Colombier break;
2617dd7cddfSDavid du Colombier default:
2627dd7cddfSDavid du Colombier fetchBodyStr(f, "", 0);
2637dd7cddfSDavid du Colombier return;
2647dd7cddfSDavid du Colombier }
2657dd7cddfSDavid du Colombier
2667dd7cddfSDavid du Colombier /*
2677dd7cddfSDavid du Colombier * read in each block, convert \n without \r to \r\n.
2687dd7cddfSDavid du Colombier * this means partial fetch requires fetching everything
2697dd7cddfSDavid du Colombier * through stop, since we don't know how many \r's will be added
2707dd7cddfSDavid du Colombier */
2717dd7cddfSDavid du Colombier buf[0] = ' ';
2727dd7cddfSDavid du Colombier for(pos = 0; pos < stop; ){
2737dd7cddfSDavid du Colombier n = BufSize;
2747dd7cddfSDavid du Colombier if(n > stop - pos)
2757dd7cddfSDavid du Colombier n = stop - pos;
2767dd7cddfSDavid du Colombier n = read(fd, &buf[1], n);
2777dd7cddfSDavid du Colombier if(n <= 0){
2787dd7cddfSDavid du Colombier fetchBodyFill(stop - pos);
2797dd7cddfSDavid du Colombier break;
2807dd7cddfSDavid du Colombier }
2817dd7cddfSDavid du Colombier e = &buf[n + 1];
2827dd7cddfSDavid du Colombier *e = '\0';
2837dd7cddfSDavid du Colombier for(s = &buf[1]; s < e && pos < stop; s = t + 1){
2847dd7cddfSDavid du Colombier t = memchr(s, '\n', e - s);
2857dd7cddfSDavid du Colombier if(t == nil)
2867dd7cddfSDavid du Colombier t = e;
2877dd7cddfSDavid du Colombier n = t - s;
2887dd7cddfSDavid du Colombier if(pos < start){
2897dd7cddfSDavid du Colombier if(pos + n <= start){
2907dd7cddfSDavid du Colombier s = t;
2917dd7cddfSDavid du Colombier pos += n;
2927dd7cddfSDavid du Colombier }else{
2937dd7cddfSDavid du Colombier s += start - pos;
2947dd7cddfSDavid du Colombier pos = start;
2957dd7cddfSDavid du Colombier }
2967dd7cddfSDavid du Colombier n = t - s;
2977dd7cddfSDavid du Colombier }
2987dd7cddfSDavid du Colombier nn = n;
2997dd7cddfSDavid du Colombier if(pos + nn > stop)
3007dd7cddfSDavid du Colombier nn = stop - pos;
3017dd7cddfSDavid du Colombier if(Bwrite(&bout, s, nn) != nn)
3027dd7cddfSDavid du Colombier writeErr();
3037dd7cddfSDavid du Colombier pos += n;
3047dd7cddfSDavid du Colombier if(*t == '\n'){
3057dd7cddfSDavid du Colombier if(t[-1] != '\r'){
3067dd7cddfSDavid du Colombier if(pos >= start && pos < stop)
3077dd7cddfSDavid du Colombier Bputc(&bout, '\r');
3087dd7cddfSDavid du Colombier pos++;
3097dd7cddfSDavid du Colombier }
3107dd7cddfSDavid du Colombier if(pos >= start && pos < stop)
3117dd7cddfSDavid du Colombier Bputc(&bout, '\n');
3127dd7cddfSDavid du Colombier pos++;
3137dd7cddfSDavid du Colombier }
3147dd7cddfSDavid du Colombier }
3157dd7cddfSDavid du Colombier buf[0] = e[-1];
3167dd7cddfSDavid du Colombier }
3177dd7cddfSDavid du Colombier close(fd);
3187dd7cddfSDavid du Colombier }
3197dd7cddfSDavid du Colombier
3207dd7cddfSDavid du Colombier /*
3217dd7cddfSDavid du Colombier * resolve the actual bounds of any partial fetch,
3227dd7cddfSDavid du Colombier * and print out the bounds & size of string returned
3237dd7cddfSDavid du Colombier */
3247dd7cddfSDavid du Colombier Pair
fetchBodyPart(Fetch * f,ulong size)3257dd7cddfSDavid du Colombier fetchBodyPart(Fetch *f, ulong size)
3267dd7cddfSDavid du Colombier {
3277dd7cddfSDavid du Colombier Pair p;
3287dd7cddfSDavid du Colombier ulong start, stop;
3297dd7cddfSDavid du Colombier
3307dd7cddfSDavid du Colombier start = 0;
3317dd7cddfSDavid du Colombier stop = size;
3327dd7cddfSDavid du Colombier if(f->partial){
3337dd7cddfSDavid du Colombier start = f->start;
3347dd7cddfSDavid du Colombier if(start > size)
3357dd7cddfSDavid du Colombier start = size;
3367dd7cddfSDavid du Colombier stop = start + f->size;
3377dd7cddfSDavid du Colombier if(stop > size)
3387dd7cddfSDavid du Colombier stop = size;
3397dd7cddfSDavid du Colombier Bprint(&bout, "<%lud>", start);
3407dd7cddfSDavid du Colombier }
3417dd7cddfSDavid du Colombier Bprint(&bout, " {%lud}\r\n", stop - start);
3427dd7cddfSDavid du Colombier p.start = start;
3437dd7cddfSDavid du Colombier p.stop = stop;
3447dd7cddfSDavid du Colombier return p;
3457dd7cddfSDavid du Colombier }
3467dd7cddfSDavid du Colombier
3477dd7cddfSDavid du Colombier /*
3487dd7cddfSDavid du Colombier * something went wrong fetching data
3497dd7cddfSDavid du Colombier * produce fill bytes for what we've committed to produce
3507dd7cddfSDavid du Colombier */
3517dd7cddfSDavid du Colombier void
fetchBodyFill(ulong n)3527dd7cddfSDavid du Colombier fetchBodyFill(ulong n)
3537dd7cddfSDavid du Colombier {
3547dd7cddfSDavid du Colombier while(n-- > 0)
3557dd7cddfSDavid du Colombier if(Bputc(&bout, ' ') < 0)
3567dd7cddfSDavid du Colombier writeErr();
3577dd7cddfSDavid du Colombier }
3587dd7cddfSDavid du Colombier
3597dd7cddfSDavid du Colombier /*
3607dd7cddfSDavid du Colombier * return a simple string
3617dd7cddfSDavid du Colombier */
3627dd7cddfSDavid du Colombier void
fetchBodyStr(Fetch * f,char * buf,ulong size)3637dd7cddfSDavid du Colombier fetchBodyStr(Fetch *f, char *buf, ulong size)
3647dd7cddfSDavid du Colombier {
3657dd7cddfSDavid du Colombier Pair p;
3667dd7cddfSDavid du Colombier
3677dd7cddfSDavid du Colombier p = fetchBodyPart(f, size);
3687dd7cddfSDavid du Colombier Bwrite(&bout, &buf[p.start], p.stop-p.start);
3697dd7cddfSDavid du Colombier }
3707dd7cddfSDavid du Colombier
3719a747e4fSDavid du Colombier char*
printnlist(NList * sect)3729a747e4fSDavid du Colombier printnlist(NList *sect)
3739a747e4fSDavid du Colombier {
3749a747e4fSDavid du Colombier static char buf[100];
3759a747e4fSDavid du Colombier char *p;
3769a747e4fSDavid du Colombier
3779a747e4fSDavid du Colombier for(p= buf; sect; sect=sect->next){
3789a747e4fSDavid du Colombier p += sprint(p, "%ld", sect->n);
3799a747e4fSDavid du Colombier if(sect->next)
3809a747e4fSDavid du Colombier *p++ = '.';
3819a747e4fSDavid du Colombier }
3829a747e4fSDavid du Colombier *p = '\0';
3839a747e4fSDavid du Colombier return buf;
3849a747e4fSDavid du Colombier }
3859a747e4fSDavid du Colombier
3867dd7cddfSDavid du Colombier /*
3877dd7cddfSDavid du Colombier * find the numbered sub-part of the message
3887dd7cddfSDavid du Colombier */
3897dd7cddfSDavid du Colombier Msg*
findMsgSect(Msg * m,NList * sect)3907dd7cddfSDavid du Colombier findMsgSect(Msg *m, NList *sect)
3917dd7cddfSDavid du Colombier {
3927dd7cddfSDavid du Colombier ulong id;
3937dd7cddfSDavid du Colombier
3947dd7cddfSDavid du Colombier for(; sect != nil; sect = sect->next){
3957dd7cddfSDavid du Colombier id = sect->n;
3969a747e4fSDavid du Colombier #ifdef HACK
3979a747e4fSDavid du Colombier /* HACK to solve extra level of structure not visible from upas/fs */
3989a747e4fSDavid du Colombier if(m->kids == 0 && id == 1 && sect->next == nil){
3999a747e4fSDavid du Colombier if(m->mime.type->s && strcmp(m->mime.type->s, "message")==0)
4009a747e4fSDavid du Colombier if(m->mime.type->t && strcmp(m->mime.type->t, "rfc822")==0)
4019a747e4fSDavid du Colombier if(m->head.type->s && strcmp(m->head.type->s, "text")==0)
4029a747e4fSDavid du Colombier if(m->head.type->t && strcmp(m->head.type->t, "plain")==0)
4039a747e4fSDavid du Colombier break;
4049a747e4fSDavid du Colombier }
4059a747e4fSDavid du Colombier /* end of HACK */
4069a747e4fSDavid du Colombier #endif HACK
4077dd7cddfSDavid du Colombier for(m = m->kids; m != nil; m = m->next)
4087dd7cddfSDavid du Colombier if(m->id == id)
4097dd7cddfSDavid du Colombier break;
4107dd7cddfSDavid du Colombier if(m == nil)
4117dd7cddfSDavid du Colombier return nil;
4127dd7cddfSDavid du Colombier }
4137dd7cddfSDavid du Colombier return m;
4147dd7cddfSDavid du Colombier }
4157dd7cddfSDavid du Colombier
4167dd7cddfSDavid du Colombier void
fetchEnvelope(Msg * m)4177dd7cddfSDavid du Colombier fetchEnvelope(Msg *m)
4187dd7cddfSDavid du Colombier {
4197dd7cddfSDavid du Colombier Tm tm;
4207dd7cddfSDavid du Colombier
4217dd7cddfSDavid du Colombier Bputc(&bout, '(');
4227dd7cddfSDavid du Colombier Brfc822date(&bout, date2tm(&tm, m->info[IDate]));
4237dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4247dd7cddfSDavid du Colombier Bimapstr(&bout, m->info[ISubject]);
4257dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4267dd7cddfSDavid du Colombier Bimapaddr(&bout, m->from);
4277dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4287dd7cddfSDavid du Colombier Bimapaddr(&bout, m->sender);
4297dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4307dd7cddfSDavid du Colombier Bimapaddr(&bout, m->replyTo);
4317dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4327dd7cddfSDavid du Colombier Bimapaddr(&bout, m->to);
4337dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4347dd7cddfSDavid du Colombier Bimapaddr(&bout, m->cc);
4357dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4367dd7cddfSDavid du Colombier Bimapaddr(&bout, m->bcc);
4377dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4387dd7cddfSDavid du Colombier Bimapstr(&bout, m->info[IInReplyTo]);
4397dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4407dd7cddfSDavid du Colombier Bimapstr(&bout, m->info[IMessageId]);
4417dd7cddfSDavid du Colombier Bputc(&bout, ')');
4427dd7cddfSDavid du Colombier }
4437dd7cddfSDavid du Colombier
4447dd7cddfSDavid du Colombier void
fetchBodyStruct(Msg * m,Header * h,int extensions)4457dd7cddfSDavid du Colombier fetchBodyStruct(Msg *m, Header *h, int extensions)
4467dd7cddfSDavid du Colombier {
4477dd7cddfSDavid du Colombier Msg *k;
4487dd7cddfSDavid du Colombier ulong len;
4497dd7cddfSDavid du Colombier
4507dd7cddfSDavid du Colombier if(msgIsMulti(h)){
4517dd7cddfSDavid du Colombier Bputc(&bout, '(');
4527dd7cddfSDavid du Colombier for(k = m->kids; k != nil; k = k->next)
4537dd7cddfSDavid du Colombier fetchBodyStruct(k, &k->mime, extensions);
4547dd7cddfSDavid du Colombier
4557dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4567dd7cddfSDavid du Colombier Bimapstr(&bout, h->type->t);
4577dd7cddfSDavid du Colombier
4587dd7cddfSDavid du Colombier if(extensions){
4597dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4607dd7cddfSDavid du Colombier BimapMimeParams(&bout, h->type->next);
4617dd7cddfSDavid du Colombier fetchStructExt(h);
4627dd7cddfSDavid du Colombier }
4637dd7cddfSDavid du Colombier
4647dd7cddfSDavid du Colombier Bputc(&bout, ')');
4657dd7cddfSDavid du Colombier return;
4667dd7cddfSDavid du Colombier }
4677dd7cddfSDavid du Colombier
4687dd7cddfSDavid du Colombier Bputc(&bout, '(');
4697dd7cddfSDavid du Colombier if(h->type != nil){
4707dd7cddfSDavid du Colombier Bimapstr(&bout, h->type->s);
4717dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4727dd7cddfSDavid du Colombier Bimapstr(&bout, h->type->t);
4737dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4747dd7cddfSDavid du Colombier BimapMimeParams(&bout, h->type->next);
4757dd7cddfSDavid du Colombier }else
4767dd7cddfSDavid du Colombier Bprint(&bout, "\"text\" \"plain\" NIL");
4777dd7cddfSDavid du Colombier
4787dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4797dd7cddfSDavid du Colombier if(h->id != nil)
4807dd7cddfSDavid du Colombier Bimapstr(&bout, h->id->s);
4817dd7cddfSDavid du Colombier else
4827dd7cddfSDavid du Colombier Bprint(&bout, "NIL");
4837dd7cddfSDavid du Colombier
4847dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4857dd7cddfSDavid du Colombier if(h->description != nil)
4867dd7cddfSDavid du Colombier Bimapstr(&bout, h->description->s);
4877dd7cddfSDavid du Colombier else
4887dd7cddfSDavid du Colombier Bprint(&bout, "NIL");
4897dd7cddfSDavid du Colombier
4907dd7cddfSDavid du Colombier Bputc(&bout, ' ');
4917dd7cddfSDavid du Colombier if(h->encoding != nil)
4927dd7cddfSDavid du Colombier Bimapstr(&bout, h->encoding->s);
4937dd7cddfSDavid du Colombier else
4947dd7cddfSDavid du Colombier Bprint(&bout, "NIL");
4957dd7cddfSDavid du Colombier
4967dd7cddfSDavid du Colombier /*
4977dd7cddfSDavid du Colombier * this is so strange: return lengths for a body[text] response,
4989a747e4fSDavid du Colombier * except in the case of a multipart message, when return lengths for a body[] response
4997dd7cddfSDavid du Colombier */
5007dd7cddfSDavid du Colombier len = m->size;
5017dd7cddfSDavid du Colombier if(h == &m->mime)
5027dd7cddfSDavid du Colombier len += m->head.size;
5037dd7cddfSDavid du Colombier Bprint(&bout, " %lud", len);
5047dd7cddfSDavid du Colombier
5057dd7cddfSDavid du Colombier len = m->lines;
5067dd7cddfSDavid du Colombier if(h == &m->mime)
5077dd7cddfSDavid du Colombier len += m->head.lines;
5087dd7cddfSDavid du Colombier
5097dd7cddfSDavid du Colombier if(h->type == nil || cistrcmp(h->type->s, "text") == 0){
5107dd7cddfSDavid du Colombier Bprint(&bout, " %lud", len);
5117dd7cddfSDavid du Colombier }else if(msgIsRfc822(h)){
5127dd7cddfSDavid du Colombier Bputc(&bout, ' ');
5137dd7cddfSDavid du Colombier k = m;
5147dd7cddfSDavid du Colombier if(h != &m->mime)
5157dd7cddfSDavid du Colombier k = m->kids;
5167dd7cddfSDavid du Colombier if(k == nil)
5177dd7cddfSDavid du Colombier Bprint(&bout, "(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) (\"text\" \"plain\" NIL NIL NIL NIL 0 0) 0");
5187dd7cddfSDavid du Colombier else{
5197dd7cddfSDavid du Colombier fetchEnvelope(k);
5207dd7cddfSDavid du Colombier Bputc(&bout, ' ');
5217dd7cddfSDavid du Colombier fetchBodyStruct(k, &k->head, extensions);
5227dd7cddfSDavid du Colombier Bprint(&bout, " %lud", len);
5237dd7cddfSDavid du Colombier }
5247dd7cddfSDavid du Colombier }
5257dd7cddfSDavid du Colombier
5267dd7cddfSDavid du Colombier if(extensions){
5277dd7cddfSDavid du Colombier Bputc(&bout, ' ');
5287dd7cddfSDavid du Colombier
5297dd7cddfSDavid du Colombier /*
5307dd7cddfSDavid du Colombier * don't have the md5 laying around,
5317dd7cddfSDavid du Colombier * since the header & body have added newlines.
5327dd7cddfSDavid du Colombier */
5337dd7cddfSDavid du Colombier Bprint(&bout, "NIL");
5347dd7cddfSDavid du Colombier
5357dd7cddfSDavid du Colombier fetchStructExt(h);
5367dd7cddfSDavid du Colombier }
5377dd7cddfSDavid du Colombier Bputc(&bout, ')');
5387dd7cddfSDavid du Colombier }
5397dd7cddfSDavid du Colombier
5407dd7cddfSDavid du Colombier /*
5417dd7cddfSDavid du Colombier * common part of bodystructure extensions
5427dd7cddfSDavid du Colombier */
5437dd7cddfSDavid du Colombier void
fetchStructExt(Header * h)5447dd7cddfSDavid du Colombier fetchStructExt(Header *h)
5457dd7cddfSDavid du Colombier {
5467dd7cddfSDavid du Colombier Bputc(&bout, ' ');
5477dd7cddfSDavid du Colombier if(h->disposition != nil){
5487dd7cddfSDavid du Colombier Bputc(&bout, '(');
5497dd7cddfSDavid du Colombier Bimapstr(&bout, h->disposition->s);
5507dd7cddfSDavid du Colombier Bputc(&bout, ' ');
5517dd7cddfSDavid du Colombier BimapMimeParams(&bout, h->disposition->next);
5527dd7cddfSDavid du Colombier Bputc(&bout, ')');
5537dd7cddfSDavid du Colombier }else
5547dd7cddfSDavid du Colombier Bprint(&bout, "NIL");
5557dd7cddfSDavid du Colombier Bputc(&bout, ' ');
5567dd7cddfSDavid du Colombier if(h->language != nil){
5577dd7cddfSDavid du Colombier if(h->language->next != nil)
5587dd7cddfSDavid du Colombier BimapMimeParams(&bout, h->language->next);
5597dd7cddfSDavid du Colombier else
5607dd7cddfSDavid du Colombier Bimapstr(&bout, h->language->s);
5617dd7cddfSDavid du Colombier }else
5627dd7cddfSDavid du Colombier Bprint(&bout, "NIL");
5637dd7cddfSDavid du Colombier }
5647dd7cddfSDavid du Colombier
5657dd7cddfSDavid du Colombier int
BimapMimeParams(Biobuf * b,MimeHdr * mh)5667dd7cddfSDavid du Colombier BimapMimeParams(Biobuf *b, MimeHdr *mh)
5677dd7cddfSDavid du Colombier {
5687dd7cddfSDavid du Colombier char *sep;
5697dd7cddfSDavid du Colombier int n;
5707dd7cddfSDavid du Colombier
5717dd7cddfSDavid du Colombier if(mh == nil)
5727dd7cddfSDavid du Colombier return Bprint(b, "NIL");
5737dd7cddfSDavid du Colombier
5747dd7cddfSDavid du Colombier n = Bputc(b, '(');
5757dd7cddfSDavid du Colombier
5767dd7cddfSDavid du Colombier sep = "";
5777dd7cddfSDavid du Colombier for(; mh != nil; mh = mh->next){
5787dd7cddfSDavid du Colombier n += Bprint(b, sep);
5797dd7cddfSDavid du Colombier n += Bimapstr(b, mh->s);
5807dd7cddfSDavid du Colombier n += Bputc(b, ' ');
5817dd7cddfSDavid du Colombier n += Bimapstr(b, mh->t);
5827dd7cddfSDavid du Colombier sep = " ";
5837dd7cddfSDavid du Colombier }
5847dd7cddfSDavid du Colombier
5857dd7cddfSDavid du Colombier n += Bputc(b, ')');
5867dd7cddfSDavid du Colombier return n;
5877dd7cddfSDavid du Colombier }
5887dd7cddfSDavid du Colombier
5897dd7cddfSDavid du Colombier /*
5907dd7cddfSDavid du Colombier * print a list of addresses;
5917dd7cddfSDavid du Colombier * each address is printed as '(' personalName AtDomainList mboxName hostName ')'
5927dd7cddfSDavid du Colombier * the AtDomainList is always NIL
5937dd7cddfSDavid du Colombier */
5947dd7cddfSDavid du Colombier int
Bimapaddr(Biobuf * b,MAddr * a)5957dd7cddfSDavid du Colombier Bimapaddr(Biobuf *b, MAddr *a)
5967dd7cddfSDavid du Colombier {
5977dd7cddfSDavid du Colombier char *host, *sep;
5987dd7cddfSDavid du Colombier int n;
5997dd7cddfSDavid du Colombier
6007dd7cddfSDavid du Colombier if(a == nil)
6017dd7cddfSDavid du Colombier return Bprint(b, "NIL");
6027dd7cddfSDavid du Colombier
6037dd7cddfSDavid du Colombier n = Bputc(b, '(');
6047dd7cddfSDavid du Colombier sep = "";
6057dd7cddfSDavid du Colombier for(; a != nil; a = a->next){
6067dd7cddfSDavid du Colombier n += Bprint(b, "%s(", sep);
6077dd7cddfSDavid du Colombier n += Bimapstr(b, a->personal);
6087dd7cddfSDavid du Colombier n += Bprint(b," NIL ");
6097dd7cddfSDavid du Colombier n += Bimapstr(b, a->box);
6107dd7cddfSDavid du Colombier n += Bputc(b, ' ');
6117dd7cddfSDavid du Colombier
6127dd7cddfSDavid du Colombier /*
6137dd7cddfSDavid du Colombier * can't send NIL as hostName, since that is code for a group
6147dd7cddfSDavid du Colombier */
6157dd7cddfSDavid du Colombier host = a->host;
6167dd7cddfSDavid du Colombier if(host == nil)
6177dd7cddfSDavid du Colombier host = "";
6187dd7cddfSDavid du Colombier n += Bimapstr(b, host);
6197dd7cddfSDavid du Colombier
6207dd7cddfSDavid du Colombier n += Bputc(b, ')');
6217dd7cddfSDavid du Colombier sep = " ";
6227dd7cddfSDavid du Colombier }
6237dd7cddfSDavid du Colombier n += Bputc(b, ')');
6247dd7cddfSDavid du Colombier return n;
6257dd7cddfSDavid du Colombier }
626