f2ffa27d42d6dc5a93119ed3b0670b29883028ed
[apps/madmutt.git] / headers.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
4  *
5  * This file is part of mutt-ng, see http://www.muttng.org/.
6  * It's licensed under the GNU General Public License,
7  * please see the file GPL in the top level source directory.
8  */
9
10 #if HAVE_CONFIG_H
11 # include "config.h"
12 #endif
13
14 #include "mutt.h"
15 #include "mutt_crypt.h"
16 #include "mutt_idna.h"
17
18 #include <sys/stat.h>
19 #include <string.h>
20 #include <ctype.h>
21
22 void mutt_edit_headers (const char *editor,
23                         const char *body,
24                         HEADER * msg, char *fcc, size_t fcclen)
25 {
26   char path[_POSIX_PATH_MAX];   /* tempfile used to edit headers + body */
27   char buffer[LONG_STRING];
28   char *p;
29   FILE *ifp, *ofp;
30   int i, keep;
31   ENVELOPE *n;
32   time_t mtime;
33   struct stat st;
34   LIST *cur, **last = NULL, *tmp;
35
36   mutt_mktemp (path);
37   if ((ofp = safe_fopen (path, "w")) == NULL) {
38     mutt_perror (path);
39     return;
40   }
41
42   mutt_env_to_local (msg->env);
43   mutt_write_rfc822_header (ofp, msg->env, NULL, 1, 0);
44   fputc ('\n', ofp);            /* tie off the header. */
45
46   /* now copy the body of the message. */
47   if ((ifp = fopen (body, "r")) == NULL) {
48     mutt_perror (body);
49     return;
50   }
51
52   mutt_copy_stream (ifp, ofp);
53
54   fclose (ifp);
55   fclose (ofp);
56
57   if (stat (path, &st) == -1) {
58     mutt_perror (path);
59     return;
60   }
61
62   mtime = mutt_decrease_mtime (path, &st);
63
64   mutt_edit_file (editor, path);
65   stat (path, &st);
66   if (mtime == st.st_mtime) {
67     dprint (1,
68             (debugfile, "ci_edit_headers(): temp file was not modified.\n"));
69     /* the file has not changed! */
70     mutt_unlink (path);
71     return;
72   }
73
74   mutt_unlink (body);
75   mutt_free_list (&msg->env->userhdrs);
76
77   /* Read the temp file back in */
78   if ((ifp = fopen (path, "r")) == NULL) {
79     mutt_perror (path);
80     return;
81   }
82
83   if ((ofp = safe_fopen (body, "w")) == NULL) {
84     /* intentionally leak a possible temporary file here */
85     fclose (ifp);
86     mutt_perror (body);
87     return;
88   }
89
90   n = mutt_read_rfc822_header (ifp, NULL, 1, 0);
91   while ((i = fread (buffer, 1, sizeof (buffer), ifp)) > 0)
92     fwrite (buffer, 1, i, ofp);
93   fclose (ofp);
94   fclose (ifp);
95   mutt_unlink (path);
96
97   /* restore old info. */
98   n->references = msg->env->references;
99   msg->env->references = NULL;
100
101   mutt_free_envelope (&msg->env);
102   msg->env = n;
103   n = NULL;
104
105   if (!msg->env->in_reply_to)
106 #ifdef USE_NNTP
107     if (!option (OPTNEWSSEND))
108 #endif
109       mutt_free_list (&msg->env->references);
110
111   mutt_expand_aliases_env (msg->env);
112
113   /* search through the user defined headers added to see if either a 
114    * fcc: or attach-file: field was specified.  
115    */
116
117   cur = msg->env->userhdrs;
118   last = &msg->env->userhdrs;
119   while (cur) {
120     keep = 1;
121
122     /* keep track of whether or not we see the in-reply-to field.  if we did
123      * not, remove the references: field later so that we can generate a new
124      * message based upon this one.
125      */
126     if (fcc && ascii_strncasecmp ("fcc:", cur->data, 4) == 0) {
127       p = cur->data + 4;
128       SKIPWS (p);
129       if (*p) {
130         strfcpy (fcc, p, fcclen);
131         mutt_pretty_mailbox (fcc);
132       }
133       keep = 0;
134     }
135     else if (ascii_strncasecmp ("attach:", cur->data, 7) == 0) {
136       BODY *body;
137       BODY *parts;
138       char *q;
139
140       p = cur->data + 7;
141       SKIPWS (p);
142       if (*p) {
143         if ((q = strpbrk (p, " \t"))) {
144           mutt_substrcpy (path, p, q, sizeof (path));
145           SKIPWS (q);
146         }
147         else
148           strfcpy (path, p, sizeof (path));
149         mutt_expand_path (path, sizeof (path));
150         if ((body = mutt_make_file_attach (path))) {
151           body->description = safe_strdup (q);
152           for (parts = msg->content; parts->next; parts = parts->next);
153           parts->next = body;
154         }
155         else {
156           mutt_pretty_mailbox (path);
157           mutt_error (_("%s: unable to attach file"), path);
158         }
159       }
160       keep = 0;
161     }
162
163
164     else if ((WithCrypto & APPLICATION_PGP)
165              && ascii_strncasecmp ("pgp:", cur->data, 4) == 0) {
166       msg->security = mutt_parse_crypt_hdr (cur->data + 4, 0);
167       if (msg->security)
168         msg->security |= APPLICATION_PGP;
169       keep = 0;
170     }
171
172     if (keep) {
173       last = &cur->next;
174       cur = cur->next;
175     }
176     else {
177       tmp = cur;
178       *last = cur->next;
179       cur = cur->next;
180       tmp->next = NULL;
181       mutt_free_list (&tmp);
182     }
183   }
184 }