b4e28a3d9a36725ae0d5f6e3c32d0ad83f95a86a
[apps/madmutt.git] / editmsg.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.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 /* simple, editor-based message editing */
11
12 #if HAVE_CONFIG_H
13 # include "config.h"
14 #endif
15
16 #include "mutt.h"
17 #include "copy.h"
18 #include "mailbox.h"
19 #include "mx.h"
20
21 #include <sys/stat.h>
22 #include <errno.h>
23
24 #include <time.h>
25
26 /*
27  * return value:
28  * 
29  * 1    message not modified
30  * 0    message edited successfully
31  * -1   error
32  */
33
34 static int edit_one_message (CONTEXT * ctx, HEADER * cur)
35 {
36   char tmp[_POSIX_PATH_MAX];
37   char buff[STRING];
38   int omagic;
39   int oerrno;
40   int rc;
41
42   unsigned short o_read;
43   unsigned short o_old;
44
45   int of, cf;
46
47   CONTEXT tmpctx;
48   MESSAGE *msg;
49
50   FILE *fp = NULL;
51
52   struct stat sb;
53   time_t mtime = 0;
54
55   mutt_mktemp (tmp);
56
57   omagic = DefaultMagic;
58   DefaultMagic = M_MBOX;
59
60   rc = (mx_open_mailbox (tmp, M_NEWFOLDER, &tmpctx) == NULL) ? -1 : 0;
61
62   DefaultMagic = omagic;
63
64   if (rc == -1) {
65     mutt_error (_("could not create temporary folder: %s"), strerror (errno));
66     return -1;
67   }
68
69   rc = mutt_append_message (&tmpctx, ctx, cur, 0, CH_NOLEN |
70                             ((ctx->magic == M_MBOX
71                               || ctx->magic == M_MMDF) ? 0 : CH_NOSTATUS));
72   oerrno = errno;
73
74   mx_close_mailbox (&tmpctx, NULL);
75
76   if (rc == -1) {
77     mutt_error (_("could not write temporary mail folder: %s"),
78                 strerror (oerrno));
79     goto bail;
80   }
81
82   if (stat (tmp, &sb) == 0)
83     mtime = sb.st_mtime;
84
85   /*
86    * 2002-09-05 me@sigpipe.org
87    * The file the user is going to edit is not a real mbox, so we need to
88    * truncate the last newline in the temp file, which is logically part of
89    * the message separator, and not the body of the message.  If we fail to
90    * remove it, the message will grow by one line each time the user edits
91    * the message.
92    */
93   if (sb.st_size != 0 && truncate (tmp, sb.st_size - 1) == -1) {
94     mutt_error (_("could not truncate temporary mail folder: %s"),
95                 strerror (errno));
96     goto bail;
97   }
98
99   mutt_edit_file (NONULL (Editor), tmp);
100
101   if ((rc = stat (tmp, &sb)) == -1) {
102     mutt_error (_("Can't stat %s: %s"), tmp, strerror (errno));
103     goto bail;
104   }
105
106   if (sb.st_size == 0) {
107     mutt_message (_("Message file is empty!"));
108     rc = 1;
109     goto bail;
110   }
111
112   if (sb.st_mtime == mtime) {
113     mutt_message (_("Message not modified!"));
114     rc = 1;
115     goto bail;
116   }
117
118   if ((fp = fopen (tmp, "r")) == NULL) {
119     rc = -1;
120     mutt_error (_("Can't open message file: %s"), strerror (errno));
121     goto bail;
122   }
123
124   if (mx_open_mailbox (ctx->path, M_APPEND, &tmpctx) == NULL) {
125     rc = -1;
126     mutt_error (_("Can't append to folder: %s"), strerror (errno));
127     goto bail;
128   }
129
130   of = 0;
131   cf = ((tmpctx.magic == M_MBOX || tmpctx.magic == M_MMDF) ? 0 : CH_NOSTATUS);
132
133   if (fgets (buff, sizeof (buff), fp) && is_from (buff, NULL, 0, NULL)) {
134     if (tmpctx.magic == M_MBOX || tmpctx.magic == M_MMDF)
135       cf = CH_FROM | CH_FORCE_FROM;
136   }
137   else
138     of = M_ADD_FROM;
139
140   /* 
141    * XXX - we have to play games with the message flags to avoid
142    * problematic behaviour with maildir folders.
143    *
144    */
145
146   o_read = cur->read;
147   o_old = cur->old;
148   cur->read = cur->old = 0;
149   msg = mx_open_new_message (&tmpctx, cur, of);
150   cur->read = o_read;
151   cur->old = o_old;
152
153   if (msg == NULL) {
154     mutt_error (_("Can't append to folder: %s"), strerror (errno));
155     mx_close_mailbox (&tmpctx, NULL);
156     goto bail;
157   }
158
159   if ((rc =
160        mutt_copy_hdr (fp, msg->fp, 0, sb.st_size, CH_NOLEN | cf,
161                       NULL)) == 0) {
162     fputc ('\n', msg->fp);
163     rc = mutt_copy_stream (fp, msg->fp);
164   }
165
166   rc = mx_commit_message (msg, &tmpctx);
167   mx_close_message (&msg);
168
169   mx_close_mailbox (&tmpctx, NULL);
170
171 bail:
172   if (fp)
173     fclose (fp);
174
175   if (rc >= 0)
176     unlink (tmp);
177
178   if (rc == 0) {
179     mutt_set_flag (Context, cur, M_DELETE, 1);
180     mutt_set_flag (Context, cur, M_READ, 1);
181
182     if (option (OPTDELETEUNTAG))
183       mutt_set_flag (Context, cur, M_TAG, 0);
184   }
185   else if (rc == -1)
186     mutt_message (_("Error. Preserving temporary file: %s"), tmp);
187
188
189   return rc;
190 }
191
192 int mutt_edit_message (CONTEXT * ctx, HEADER * hdr)
193 {
194   int i, j;
195
196   if (hdr)
197     return edit_one_message (ctx, hdr);
198
199
200   for (i = 0; i < ctx->vcount; i++) {
201     j = ctx->v2r[i];
202     if (ctx->hdrs[j]->tagged) {
203       if (edit_one_message (ctx, ctx->hdrs[j]) == -1)
204         return -1;
205     }
206   }
207
208   return 0;
209 }