safe_fclose -> m_fclose, and is now inlined.
[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 #include <lib-lib/lib-lib.h>
11 #include <lib-ui/curses.h>
12
13 #include "mutt.h"
14 #include "alias.h"
15 #include <lib-crypt/crypt.h>
16 #include "mutt_idna.h"
17
18 void mutt_edit_headers (const char *editor,
19                         const char *body,
20                         HEADER * msg, char *fcc, ssize_t fcclen)
21 {
22   char path[_POSIX_PATH_MAX];   /* tempfile used to edit headers + body */
23   char buffer[LONG_STRING];
24   char *p;
25   FILE *ifp, *ofp;
26   int i, keep;
27   ENVELOPE *n;
28   time_t mtime;
29   struct stat st;
30   string_list_t *cur, **last = NULL, *tmp;
31
32   ofp = m_tempfile(path, sizeof(path), NONULL(Tempdir), NULL);
33   if (!ofp) {
34     mutt_perror (path);
35     return;
36   }
37
38   mutt_env_to_local (msg->env);
39   mutt_write_rfc822_header (ofp, msg->env, NULL, 1, 0);
40   fputc ('\n', ofp);            /* tie off the header. */
41
42   /* now copy the body of the message. */
43   if ((ifp = fopen (body, "r")) == NULL) {
44     mutt_perror (body);
45     return;
46   }
47
48   mutt_copy_stream (ifp, ofp);
49
50   fclose (ifp);
51   fclose (ofp);
52
53   if (stat (path, &st) == -1) {
54     mutt_perror (path);
55     return;
56   }
57
58   mtime = mutt_decrease_mtime (path, &st);
59
60   mutt_edit_file (editor, path);
61   stat (path, &st);
62   if (mtime == st.st_mtime) {
63     /* the file has not changed! */
64     mutt_unlink (path);
65     return;
66   }
67
68   mutt_unlink (body);
69   string_list_wipe(&msg->env->userhdrs);
70
71   /* Read the temp file back in */
72   if ((ifp = fopen (path, "r")) == NULL) {
73     mutt_perror (path);
74     return;
75   }
76
77   if ((ofp = safe_fopen (body, "w")) == NULL) {
78     /* intentionally leak a possible temporary file here */
79     fclose (ifp);
80     mutt_perror (body);
81     return;
82   }
83
84   n = mutt_read_rfc822_header (ifp, NULL, 1, 0);
85   while ((i = fread (buffer, 1, sizeof (buffer), ifp)) > 0)
86     fwrite (buffer, 1, i, ofp);
87   fclose (ofp);
88   fclose (ifp);
89   mutt_unlink (path);
90
91   /* restore old info. */
92   n->references = msg->env->references;
93   msg->env->references = NULL;
94
95   envelope_delete(&msg->env);
96   msg->env = n;
97   n = NULL;
98
99   if (!msg->env->in_reply_to)
100 #ifdef USE_NNTP
101     if (!option (OPTNEWSSEND))
102 #endif
103       string_list_wipe(&msg->env->references);
104
105   mutt_expand_aliases_env (msg->env);
106
107   /* search through the user defined headers added to see if either a 
108    * fcc: or attach-file: field was specified.  
109    */
110
111   cur = msg->env->userhdrs;
112   last = &msg->env->userhdrs;
113   while (cur) {
114     keep = 1;
115
116     /* keep track of whether or not we see the in-reply-to field.  if we did
117      * not, remove the references: field later so that we can generate a new
118      * message based upon this one.
119      */
120     if (fcc && ascii_strncasecmp ("fcc:", cur->data, 4) == 0) {
121       p = vskipspaces(cur->data + 4);
122       if (*p) {
123         m_strcpy(fcc, fcclen, p);
124         mutt_pretty_mailbox (fcc);
125       }
126       keep = 0;
127     }
128     else if (ascii_strncasecmp ("attach:", cur->data, 7) == 0) {
129       BODY *bbody;
130       BODY *parts;
131       char *q;
132
133       p = vskipspaces(cur->data + 7);
134       if (*p) {
135         if ((q = strpbrk (p, " \t"))) {
136           m_strncpy(path, sizeof(path), p, q - p);
137           q = vskipspaces(q);
138         }
139         else
140           m_strcpy(path, sizeof(path), p);
141         mutt_expand_path (path, sizeof (path));
142         if ((bbody = mutt_make_file_attach (path))) {
143           bbody->description = m_strdup(q);
144           for (parts = msg->content; parts->next; parts = parts->next);
145           parts->next = bbody;
146         }
147         else {
148           mutt_pretty_mailbox (path);
149           mutt_error (_("%s: unable to attach file"), path);
150         }
151       }
152       keep = 0;
153     }
154
155
156     else if (ascii_strncasecmp("pgp:", cur->data, 4) == 0) {
157       msg->security = mutt_parse_crypt_hdr (cur->data + 4, 0);
158       if (msg->security)
159         msg->security |= APPLICATION_PGP;
160       keep = 0;
161     }
162
163     if (keep) {
164       last = &cur->next;
165       cur = cur->next;
166     }
167     else {
168       tmp = cur;
169       *last = cur->next;
170       cur = cur->next;
171       tmp->next = NULL;
172       string_list_wipe(&tmp);
173     }
174   }
175 }