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