]> git.llucax.com Git - software/mutt-debian.git/blob - headers.c
Add upstream/573823-imap_internal_date
[software/mutt-debian.git] / headers.c
1 /* 
2  * Copyright (C) 1996-2009 Michael R. Elkins <me@mutt.org>
3  * 
4  *     This program is free software; you can redistribute it and/or modify
5  *     it under the terms of the GNU General Public License as published by
6  *     the Free Software Foundation; either version 2 of the License, or
7  *     (at your option) any later version.
8  * 
9  *     This program is distributed in the hope that it will be useful,
10  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *     GNU General Public License for more details.
13  * 
14  *     You should have received a copy of the GNU General Public License
15  *     along with this program; if not, write to the Free Software
16  *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18
19 #if HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #include "mutt.h"
24 #include "mutt_crypt.h"
25 #include "mutt_idna.h"
26
27 #include <sys/stat.h>
28 #include <string.h>
29 #include <ctype.h>
30
31 void mutt_edit_headers (const char *editor,
32                         const char *body,
33                         HEADER *msg,
34                         char *fcc,
35                         size_t fcclen)
36 {
37   char path[_POSIX_PATH_MAX];   /* tempfile used to edit headers + body */
38   char buffer[LONG_STRING];
39   char *p;
40   FILE *ifp, *ofp;
41   int i, keep;
42   ENVELOPE *n;
43   time_t mtime;
44   struct stat st;
45   LIST *cur, **last = NULL, *tmp;
46
47   mutt_mktemp (path);
48   if ((ofp = safe_fopen (path, "w")) == NULL)
49   {
50     mutt_perror (path);
51     return;
52   }
53   
54   mutt_env_to_local (msg->env);
55   mutt_write_rfc822_header (ofp, msg->env, NULL, 1, 0);
56   fputc ('\n', ofp);    /* tie off the header. */
57
58   /* now copy the body of the message. */
59   if ((ifp = fopen (body, "r")) == NULL)
60   {
61     mutt_perror (body);
62     return;
63   }
64
65   mutt_copy_stream (ifp, ofp);
66
67   safe_fclose (&ifp);
68   safe_fclose (&ofp);
69
70   if (stat (path, &st) == -1)
71   {
72     mutt_perror (path);
73     return;
74   }
75
76   mtime = mutt_decrease_mtime (path, &st);
77
78   mutt_edit_file (editor, path);
79   stat (path, &st);
80   if (mtime == st.st_mtime)
81   {
82     dprint (1, (debugfile, "ci_edit_headers(): temp file was not modified.\n"));
83     /* the file has not changed! */
84     mutt_unlink (path);
85     return;
86   }
87
88   mutt_unlink (body);
89   mutt_free_list (&msg->env->userhdrs);
90
91   /* Read the temp file back in */
92   if ((ifp = fopen (path, "r")) == NULL)
93   {
94     mutt_perror (path);
95     return;
96   }
97   
98   if ((ofp = safe_fopen (body, "w")) == NULL)
99   {
100     /* intentionally leak a possible temporary file here */
101     safe_fclose (&ifp);
102     mutt_perror (body);
103     return;
104   }
105   
106   n = mutt_read_rfc822_header (ifp, NULL, 1, 0);
107   while ((i = fread (buffer, 1, sizeof (buffer), ifp)) > 0)
108     fwrite (buffer, 1, i, ofp);
109   safe_fclose (&ofp);
110   safe_fclose (&ifp);
111   mutt_unlink (path);
112
113   /* in case the user modifies/removes the In-Reply-To header with
114      $edit_headers set, we remove References: as they're likely invalid;
115      we can simply compare strings as we don't generate References for
116      multiple Message-Ids in IRT anyways */
117   if (!n->in_reply_to || (msg->env->in_reply_to &&
118                           mutt_strcmp (n->in_reply_to->data,
119                                        msg->env->in_reply_to->data) != 0))
120     mutt_free_list (&msg->env->references);
121
122   /* restore old info. */
123   mutt_free_list (&n->references);
124   n->references = msg->env->references;
125   msg->env->references = NULL;
126
127   mutt_free_envelope (&msg->env);
128   msg->env = n; n = NULL;
129
130   mutt_expand_aliases_env (msg->env);
131
132   /* search through the user defined headers added to see if 
133    * fcc: or attach: or pgp: was specified
134    */
135
136   cur = msg->env->userhdrs;
137   last = &msg->env->userhdrs;
138   while (cur)
139   {
140     keep = 1;
141
142     if (fcc && ascii_strncasecmp ("fcc:", cur->data, 4) == 0)
143     {
144       p = cur->data + 4;
145       SKIPWS (p);
146       if (*p)
147       {
148         strfcpy (fcc, p, fcclen);
149         mutt_pretty_mailbox (fcc, fcclen);
150       }
151       keep = 0;
152     }
153     else if (ascii_strncasecmp ("attach:", cur->data, 7) == 0)
154     {
155       BODY *body;
156       BODY *parts;
157       int l = 0;
158
159       p = cur->data + 7;
160       SKIPWS (p);
161       if (*p)
162       {
163         for ( ; *p && *p != ' ' && *p != '\t'; p++)
164         {
165           if (*p == '\\')
166           {
167             if (!*(p+1))
168               break;
169             p++;
170           }
171           if (l < sizeof (path) - 1)
172             path[l++] = *p;
173         }
174         if (*p)
175           *p++ = 0;
176         SKIPWS (p);
177         path[l] = 0;
178
179         mutt_expand_path (path, sizeof (path));
180         if ((body = mutt_make_file_attach (path)))
181         {
182           body->description = safe_strdup (p);
183           for (parts = msg->content; parts->next; parts = parts->next) ;
184           parts->next = body;
185         }
186         else
187         {
188           mutt_pretty_mailbox (path, sizeof (path));
189           mutt_error (_("%s: unable to attach file"), path);
190         }
191       }
192       keep = 0;
193     }
194     else if ((WithCrypto & APPLICATION_PGP)
195              && ascii_strncasecmp ("pgp:", cur->data, 4) == 0)
196     {
197       msg->security = mutt_parse_crypt_hdr (cur->data + 4, 0, APPLICATION_PGP);
198       if (msg->security)
199         msg->security |= APPLICATION_PGP;
200       keep = 0;
201     }
202
203     if (keep)
204     {
205       last = &cur->next;
206       cur  = cur->next;
207     }
208     else
209     {
210       tmp       = cur;
211       *last     = cur->next;
212       cur       = cur->next;
213       tmp->next = NULL;
214       mutt_free_list (&tmp);
215     }
216   }
217 }