diff options
Diffstat (limited to 'imap/msgenvelope.c')
| -rw-r--r-- | imap/msgenvelope.c | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/imap/msgenvelope.c b/imap/msgenvelope.c new file mode 100644 index 0000000..60564df --- /dev/null +++ b/imap/msgenvelope.c @@ -0,0 +1,310 @@ +/* +** 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 <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.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; i<l; i++) + if (s[i] & 0x80) /* Illegal 8-bit header content */ + { + char *p=malloc(l+1); + + if (!p) + write_error_exit(0); + if (l) + memcpy(p, s, l); + p[l]=0; + + /* Assume UTF-8, if not, well, GIGO */ + q=rfc2047_encode_str(p, "utf-8", + rfc2047_qp_allow_any); + free(p); + if (!q) + write_error_exit(0); + s=q; + l=strlen(s); + } + + for (i=j=0; i<l; i++) + { + if (s[i] == '"' || s[i] == '\\') + { + (*writefunc)(s+j, i-j); + (*writefunc)("\\", 1); + j=i; + } + } + (*writefunc)(s+j, i-j); + if (q) + free(q); +} + +static void doenvs(void (*writefunc)(const char *, size_t), char *s) +{ +size_t i,j; +char *t=s; + + while ( s && *s && isspace((int)(unsigned char)*s)) + ++s; + + for (i=j=0; s && s[i]; i++) + if ( !isspace((int)(unsigned char)s[i])) + j=i+1; + + if (j == 0) + (*writefunc)("NIL", 3); + else + { + (*writefunc)("\"", 1); + msgappends(writefunc, s, j); + (*writefunc)("\"", 1); + } + + if (t) free(t); +} + +static void doenva(void (*writefunc)(const char *, size_t), char *s) +{ +struct rfc822t *t; +struct rfc822a *a; +int i; +char *q, *r; + + if (!s) + { + (*writefunc)("NIL", 3); + return; + } + + t=rfc822t_alloc_new(s, 0, 0); + if (!t) + { + perror("malloc"); + exit(0); + } + a=rfc822a_alloc(t); + if (!a) + { + perror("malloc"); + exit(1); + } + + if (a->naddrs == 0) + { + rfc822a_free(a); + rfc822t_free(t); + free(s); + (*writefunc)("NIL", 3); + return; + } + + (*writefunc)("(", 1); + for (i=0; i<a->naddrs; 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); +} |
