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