/* ** Copyright 1998 - 2009 Double Precision, Inc. ** See COPYING for distribution information. */ #if HAVE_CONFIG_H #include "config.h" #endif #include "rfc822/rfc822.h" #include "rfc822/rfc2047.h" #include "rfc2045/rfc2045.h" #include "imapwrite.h" #include #include #include #include #include "imapd.h" #define MAX_HEADER_SIZE 8192 static char *read_header(FILE *fp, off_t *headerpos, off_t *endhp) { size_t i=0; int c; static char headerbuf[MAX_HEADER_SIZE]; while (*headerpos < *endhp) { while ((c=getc(fp)) != '\n' && c != EOF) { if (c == '\r') c=' '; /* Otherwise Outlook croaks */ if (i < sizeof(headerbuf)-1) headerbuf[i++]=c; if ( ++*headerpos >= *endhp) break; } if (c == EOF || *headerpos >= *endhp) { *headerpos=*endhp; break; } if (c == '\n' && ++*headerpos >= *endhp) break; c=getc(fp); if (c != EOF) ungetc(c, fp); if (c == EOF) { *headerpos=*endhp; break; } if (c != ' ' && c != '\t') break; } headerbuf[i]=0; if (*headerpos == *endhp && i == 0) return (0); return (headerbuf); } void msgappends(void (*writefunc)(const char *, size_t), const char *s, size_t l) { size_t i,j; char *q=0; for (i=0; inaddrs == 0) { rfc822a_free(a); rfc822t_free(t); free(s); (*writefunc)("NIL", 3); return; } (*writefunc)("(", 1); for (i=0; inaddrs; i++) { (*writefunc)("(", 1); q=rfc822_display_name_tobuf(a, i, NULL); if (!q) { perror("malloc"); exit(1); } if (a->addrs[i].tokens == 0) { if (strcmp(q, ";") == 0) { (*writefunc)("NIL NIL NIL NIL)", 16); free(q); continue; } r=strrchr(q, ':'); if (r && r[1] == 0) *r=0; (*writefunc)("NIL NIL \"", 9); msgappends(writefunc, q, strlen(q)); (*writefunc)("\" NIL)", 6); free(q); continue; } if (a->addrs[i].name == 0) *q=0; /* rfc822_display_name_tobuf() defaults to addr, ignore. */ doenvs(writefunc, q); (*writefunc)(" NIL \"", 6); /* TODO @domain list */ q=rfc822_gettok(a->addrs[i].tokens); if (!q) { perror("malloc"); exit(1); } r=strrchr(q, '@'); if (r) *r++=0; msgappends(writefunc, q, strlen(q)); (*writefunc)("\" \"", 3); if (r) msgappends(writefunc, r, strlen(r)); (*writefunc)("\")", 2); free(q); } (*writefunc)(")", 1); rfc822a_free(a); rfc822t_free(t); free(s); } void msgenvelope(void (*writefunc)(const char *, size_t), FILE *fp, struct rfc2045 *mimep) { char *date=0, *subject=0; char *from=0, *sender=0, *replyto=0, *to=0, *cc=0, *bcc=0; char *inreplyto=0, *msgid=0; off_t start_pos, end_pos, start_body; off_t nlines, nbodylines; char *p, *q, *r; rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body, &nlines, &nbodylines); if (fseek(fp, start_pos, SEEK_SET) < 0) { perror("fseek"); exit(0); } while ((p=read_header(fp, &start_pos, &start_body)) != 0) { char **hdrp=0; size_t oldl, newl; size_t c; if ((q=strchr(p, ':')) != 0) *q++=0; for (r=p; *r; r++) *r=tolower((int)(unsigned char)*r); if (strcmp(p, "date") == 0) hdrp= &date; if (strcmp(p, "subject") == 0) hdrp= &subject; if (strcmp(p, "from") == 0) hdrp= &from; if (strcmp(p, "sender") == 0) hdrp= &sender; if (strcmp(p, "reply-to") == 0) hdrp= &replyto; if (strcmp(p, "to") == 0) hdrp= &to; if (strcmp(p, "cc") == 0) hdrp= &cc; if (strcmp(p, "bcc") == 0) hdrp= &bcc; if (strcmp(p, "in-reply-to") == 0) hdrp= &inreplyto; if (strcmp(p, "message-id") == 0) hdrp= &msgid; if (!hdrp) continue; if (!q) q=""; oldl= *hdrp ? strlen(*hdrp):0; newl= strlen(q); c=oldl+newl+1; if (c > 8192) c=8192; r= (char *)(*hdrp ? realloc(*hdrp, c+1):malloc(c+1)); if (!r) { perror("malloc"); exit(1); } if (oldl && oldl < c) r[oldl++]=','; newl=c-oldl; if (newl) memcpy(r+oldl, q, newl); r[oldl+newl]=0; *hdrp= r; } #if 1 if (!replyto) replyto=strdup(from ? from:""); if (!sender) sender=strdup(from ? from:""); if (!replyto || !sender) { perror("malloc"); exit(1); } #endif (*writefunc)("(", 1); doenvs(writefunc, date); (*writefunc)(" ", 1); doenvs(writefunc, subject); (*writefunc)(" ", 1); doenva(writefunc, from); (*writefunc)(" ", 1); doenva(writefunc, sender); (*writefunc)(" ", 1); doenva(writefunc, replyto); (*writefunc)(" ", 1); doenva(writefunc, to); (*writefunc)(" ", 1); doenva(writefunc, cc); (*writefunc)(" ", 1); doenva(writefunc, bcc); (*writefunc)(" ", 1); doenvs(writefunc, inreplyto); (*writefunc)(" ", 1); doenvs(writefunc, msgid); (*writefunc)(")", 1); }