c83d6d75ba2fa8e4e913ef78b9d89b5507fd3e98
[apps/madmutt.git] / headers.c
1 /* 
2  * Copyright (C) 1996-2000 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., 59 Temple Place - Suite 330, Boston, MA  02111, 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, char *fcc, size_t fcclen)
34 {
35   char path[_POSIX_PATH_MAX];   /* tempfile used to edit headers + body */
36   char buffer[LONG_STRING];
37   char *p;
38   FILE *ifp, *ofp;
39   int i, keep;
40   ENVELOPE *n;
41   time_t mtime;
42   struct stat st;
43   LIST *cur, **last = NULL, *tmp;
44
45   mutt_mktemp (path);
46   if ((ofp = safe_fopen (path, "w")) == NULL) {
47     mutt_perror (path);
48     return;
49   }
50
51   mutt_env_to_local (msg->env);
52   mutt_write_rfc822_header (ofp, msg->env, NULL, 1, 0);
53   fputc ('\n', ofp);            /* tie off the header. */
54
55   /* now copy the body of the message. */
56   if ((ifp = fopen (body, "r")) == NULL) {
57     mutt_perror (body);
58     return;
59   }
60
61   mutt_copy_stream (ifp, ofp);
62
63   fclose (ifp);
64   fclose (ofp);
65
66   if (stat (path, &st) == -1) {
67     mutt_perror (path);
68     return;
69   }
70
71   mtime = mutt_decrease_mtime (path, &st);
72
73   mutt_edit_file (editor, path);
74   stat (path, &st);
75   if (mtime == st.st_mtime) {
76     dprint (1,
77             (debugfile, "ci_edit_headers(): temp file was not modified.\n"));
78     /* the file has not changed! */
79     mutt_unlink (path);
80     return;
81   }
82
83   mutt_unlink (body);
84   mutt_free_list (&msg->env->userhdrs);
85
86   /* Read the temp file back in */
87   if ((ifp = fopen (path, "r")) == NULL) {
88     mutt_perror (path);
89     return;
90   }
91
92   if ((ofp = safe_fopen (body, "w")) == NULL) {
93     /* intentionally leak a possible temporary file here */
94     fclose (ifp);
95     mutt_perror (body);
96     return;
97   }
98
99   n = mutt_read_rfc822_header (ifp, NULL, 1, 0);
100   while ((i = fread (buffer, 1, sizeof (buffer), ifp)) > 0)
101     fwrite (buffer, 1, i, ofp);
102   fclose (ofp);
103   fclose (ifp);
104   mutt_unlink (path);
105
106   /* restore old info. */
107   n->references = msg->env->references;
108   msg->env->references = NULL;
109
110   mutt_free_envelope (&msg->env);
111   msg->env = n;
112   n = NULL;
113
114   if (!msg->env->in_reply_to)
115 #ifdef USE_NNTP
116     if (!option (OPTNEWSSEND))
117 #endif
118       mutt_free_list (&msg->env->references);
119
120   mutt_expand_aliases_env (msg->env);
121
122   /* search through the user defined headers added to see if either a 
123    * fcc: or attach-file: field was specified.  
124    */
125
126   cur = msg->env->userhdrs;
127   last = &msg->env->userhdrs;
128   while (cur) {
129     keep = 1;
130
131     /* keep track of whether or not we see the in-reply-to field.  if we did
132      * not, remove the references: field later so that we can generate a new
133      * message based upon this one.
134      */
135     if (fcc && ascii_strncasecmp ("fcc:", cur->data, 4) == 0) {
136       p = cur->data + 4;
137       SKIPWS (p);
138       if (*p) {
139         strfcpy (fcc, p, fcclen);
140         mutt_pretty_mailbox (fcc);
141       }
142       keep = 0;
143     }
144     else if (ascii_strncasecmp ("attach:", cur->data, 7) == 0) {
145       BODY *body;
146       BODY *parts;
147       char *q;
148
149       p = cur->data + 7;
150       SKIPWS (p);
151       if (*p) {
152         if ((q = strpbrk (p, " \t"))) {
153           mutt_substrcpy (path, p, q, sizeof (path));
154           SKIPWS (q);
155         }
156         else
157           strfcpy (path, p, sizeof (path));
158         mutt_expand_path (path, sizeof (path));
159         if ((body = mutt_make_file_attach (path))) {
160           body->description = safe_strdup (q);
161           for (parts = msg->content; parts->next; parts = parts->next);
162           parts->next = body;
163         }
164         else {
165           mutt_pretty_mailbox (path);
166           mutt_error (_("%s: unable to attach file"), path);
167         }
168       }
169       keep = 0;
170     }
171
172
173     else if ((WithCrypto & APPLICATION_PGP)
174              && ascii_strncasecmp ("pgp:", cur->data, 4) == 0) {
175       msg->security = mutt_parse_crypt_hdr (cur->data + 4, 0);
176       if (msg->security)
177         msg->security |= APPLICATION_PGP;
178       keep = 0;
179     }
180
181     if (keep) {
182       last = &cur->next;
183       cur = cur->next;
184     }
185     else {
186       tmp = cur;
187       *last = cur->next;
188       cur = cur->next;
189       tmp->next = NULL;
190       mutt_free_list (&tmp);
191     }
192   }
193 }