Back to index

courier  0.68.2
msgenvelope.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2009 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #if    HAVE_CONFIG_H
00007 #include      "config.h"
00008 #endif
00009 #include      "rfc822/rfc822.h"
00010 #include      "rfc822/rfc2047.h"
00011 #include      "rfc2045/rfc2045.h"
00012 #include      "imapwrite.h"
00013 #include      <stdio.h>
00014 #include      <ctype.h>
00015 #include      <stdlib.h>
00016 #include      <string.h>
00017 
00018 
00019 #define       MAX_HEADER_SIZE      8192
00020 
00021 static char *read_header(FILE *fp, off_t *headerpos, off_t *endhp)
00022 {
00023 size_t i=0;
00024 int    c;
00025 static char headerbuf[MAX_HEADER_SIZE];
00026 
00027        while (*headerpos < *endhp)
00028        {
00029               while ((c=getc(fp)) != '\n' && c != EOF)
00030               {
00031                      if (c == '\r')
00032                             c=' '; /* Otherwise Outlook croaks */
00033 
00034                      if (i < sizeof(headerbuf)-1)
00035                             headerbuf[i++]=c;
00036                      if ( ++*headerpos >= *endhp)       break;
00037               }
00038               if (c == EOF || *headerpos >= *endhp)
00039               {
00040                      *headerpos=*endhp;
00041                      break;
00042               }
00043               if (c == '\n' && ++*headerpos >= *endhp)  break;
00044               c=getc(fp);
00045               if (c != EOF) ungetc(c, fp);
00046               if (c == EOF)
00047               {
00048                      *headerpos=*endhp;
00049                      break;
00050               }
00051               if (c != ' ' && c != '\t')  break;
00052        }
00053        headerbuf[i]=0;
00054        if (*headerpos == *endhp && i == 0)       return (0);
00055        return (headerbuf);
00056 }
00057 
00058 void msgappends(void (*writefunc)(const char *, size_t),
00059               const char *s, size_t l)
00060 {
00061        size_t i,j;
00062        char *q=0;
00063 
00064        for (i=0; i<l; i++)
00065               if (s[i] & 0x80)     /* Illegal 8-bit header content */
00066               {
00067                      char *p=malloc(l+1);
00068 
00069                      if (!p)
00070                             write_error_exit(0);
00071                      if (l)
00072                             memcpy(p, s, l);
00073                      p[l]=0;
00074 
00075                      /* Assume UTF-8, if not, well, GIGO */
00076                      q=rfc2047_encode_str(p, "utf-8",
00077                                         rfc2047_qp_allow_any);
00078                      free(p);
00079                      if (!q)
00080                             write_error_exit(0);
00081                      s=q;
00082                      l=strlen(s);
00083               }
00084 
00085        for (i=j=0; i<l; i++)
00086        {
00087               if (s[i] == '"' || s[i] == '\\')
00088               {
00089                      (*writefunc)(s+j, i-j);
00090                      (*writefunc)("\\", 1);
00091                      j=i;
00092               }
00093        }
00094        (*writefunc)(s+j, i-j);
00095        if (q)
00096               free(q);
00097 }
00098 
00099 static void doenvs(void (*writefunc)(const char *, size_t), char *s)
00100 {
00101 size_t i,j;
00102 char   *t=s;
00103 
00104        while ( s && *s && isspace((int)(unsigned char)*s))
00105               ++s;
00106 
00107        for (i=j=0; s && s[i]; i++)
00108               if ( !isspace((int)(unsigned char)s[i]))
00109                      j=i+1;
00110 
00111        if (j == 0)
00112               (*writefunc)("NIL", 3);
00113        else
00114        {
00115               (*writefunc)("\"", 1);
00116               msgappends(writefunc, s, j);
00117               (*writefunc)("\"", 1);
00118        }
00119 
00120        if (t) free(t);
00121 }
00122 
00123 static void doenva(void (*writefunc)(const char *, size_t), char *s)
00124 {
00125 struct rfc822t *t;
00126 struct rfc822a *a;
00127 int    i;
00128 char   *q, *r;
00129 
00130        if (!s)
00131        {
00132               (*writefunc)("NIL", 3);
00133               return;
00134        }
00135 
00136        t=rfc822t_alloc_new(s, 0, 0);
00137        if (!t)
00138        {
00139               perror("malloc");
00140               exit(0);
00141        }
00142        a=rfc822a_alloc(t);
00143        if (!a)
00144        {
00145               perror("malloc");
00146               exit(1);
00147        }
00148 
00149        if (a->naddrs == 0)
00150        {
00151               rfc822a_free(a);
00152               rfc822t_free(t);
00153               free(s);
00154               (*writefunc)("NIL", 3);
00155               return;
00156        }
00157 
00158        (*writefunc)("(", 1);
00159        for (i=0; i<a->naddrs; i++)
00160        {
00161               (*writefunc)("(", 1);
00162 
00163               q=rfc822_display_name_tobuf(a, i, NULL);
00164 
00165               if (!q)
00166               {
00167                      perror("malloc");
00168                      exit(1);
00169               }
00170               if (a->addrs[i].tokens == 0)
00171               {
00172                      if (strcmp(q, ";") == 0)
00173                      {
00174                             (*writefunc)("NIL NIL NIL NIL)", 16);
00175                             free(q);
00176                             continue;
00177                      }
00178                      r=strrchr(q, ':');
00179                      if (r && r[1] == 0)  *r=0;
00180 
00181                      (*writefunc)("NIL NIL \"", 9);
00182                      msgappends(writefunc, q, strlen(q));
00183                      (*writefunc)("\" NIL)", 6);
00184                      free(q);
00185                      continue;
00186               }
00187 
00188               if (a->addrs[i].name == 0)
00189                      *q=0;
00190               /* rfc822_display_name_tobuf() defaults to addr, ignore. */
00191 
00192               doenvs(writefunc, q);
00193               (*writefunc)(" NIL \"", 6); /* TODO @domain list */
00194               q=rfc822_gettok(a->addrs[i].tokens);
00195               if (!q)
00196               {
00197                      perror("malloc");
00198                      exit(1);
00199               }
00200               r=strrchr(q, '@');
00201               if (r) *r++=0;
00202               msgappends(writefunc, q, strlen(q));
00203               (*writefunc)("\" \"", 3);
00204               if (r)
00205                      msgappends(writefunc, r, strlen(r));
00206               (*writefunc)("\")", 2);
00207               free(q);
00208        }
00209        (*writefunc)(")", 1);
00210        rfc822a_free(a);
00211        rfc822t_free(t);
00212        free(s);
00213 }
00214 
00215 void msgenvelope(void (*writefunc)(const char *, size_t),
00216               FILE *fp, struct rfc2045 *mimep)
00217 {
00218 char   *date=0, *subject=0;
00219 char   *from=0, *sender=0, *replyto=0, *to=0, *cc=0, *bcc=0;
00220 char   *inreplyto=0, *msgid=0;
00221 
00222 off_t start_pos, end_pos, start_body;
00223 off_t nlines, nbodylines;
00224 
00225 char   *p, *q, *r;
00226 
00227        rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
00228               &nlines, &nbodylines);
00229 
00230        if (fseek(fp, start_pos, SEEK_SET) < 0)
00231        {
00232               perror("fseek");
00233               exit(0);
00234        }
00235 
00236        while ((p=read_header(fp, &start_pos, &start_body)) != 0)
00237        {
00238        char   **hdrp=0;
00239        size_t oldl, newl;
00240        size_t c;
00241 
00242               if ((q=strchr(p, ':')) != 0)
00243                      *q++=0;
00244               for (r=p; *r; r++)
00245                      *r=tolower((int)(unsigned char)*r);
00246               if (strcmp(p, "date") == 0) hdrp= &date;
00247               if (strcmp(p, "subject") == 0)     hdrp= &subject;
00248               if (strcmp(p, "from") == 0) hdrp= &from;
00249               if (strcmp(p, "sender") == 0)      hdrp= &sender;
00250               if (strcmp(p, "reply-to") == 0)    hdrp= &replyto;
00251               if (strcmp(p, "to") == 0)   hdrp= &to;
00252               if (strcmp(p, "cc") == 0)   hdrp= &cc;
00253               if (strcmp(p, "bcc") == 0)  hdrp= &bcc;
00254               if (strcmp(p, "in-reply-to") == 0) hdrp= &inreplyto;
00255               if (strcmp(p, "message-id") == 0) hdrp= &msgid;
00256               if (!hdrp)    continue;
00257               if (!q)       q="";
00258               oldl= *hdrp ? strlen(*hdrp):0;
00259               newl= strlen(q);
00260               c=oldl+newl+1;
00261               if (c > 8192) c=8192;
00262               r= (char *)(*hdrp ? realloc(*hdrp, c+1):malloc(c+1));
00263               if (!r)
00264               {
00265                      perror("malloc");
00266                      exit(1);
00267               }
00268               if (oldl && oldl < c)
00269                      r[oldl++]=',';
00270               newl=c-oldl;
00271               if (newl)     memcpy(r+oldl, q, newl);
00272               r[oldl+newl]=0;
00273               *hdrp= r;
00274        }
00275 
00276 #if 1
00277        if (!replyto)
00278               replyto=strdup(from ? from:"");
00279        if (!sender)
00280               sender=strdup(from ? from:"");
00281 
00282        if (!replyto || !sender)
00283        {
00284               perror("malloc");
00285               exit(1);
00286        }
00287 #endif
00288 
00289        (*writefunc)("(", 1);
00290        doenvs(writefunc, date);
00291        (*writefunc)(" ", 1);
00292        doenvs(writefunc, subject);
00293        (*writefunc)(" ", 1);
00294        doenva(writefunc, from);
00295        (*writefunc)(" ", 1);
00296        doenva(writefunc, sender);
00297        (*writefunc)(" ", 1);
00298        doenva(writefunc, replyto);
00299        (*writefunc)(" ", 1);
00300        doenva(writefunc, to);
00301        (*writefunc)(" ", 1);
00302        doenva(writefunc, cc);
00303        (*writefunc)(" ", 1);
00304        doenva(writefunc, bcc);
00305        (*writefunc)(" ", 1);
00306        doenvs(writefunc, inreplyto);
00307        (*writefunc)(" ", 1);
00308        doenvs(writefunc, msgid);
00309        (*writefunc)(")", 1);
00310 }