mutt stable branch with some hacks
1/*
2 * Copyright (C) 1999-2002 Thomas Roessler <roessler@does-not-exist.org>
3 *
4 * This program is free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later
8 * version.
9 *
10 * This program is distributed in the hope that it will be
11 * useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more
14 * details.
15 *
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22/* simple, editor-based message editing */
23
24#if HAVE_CONFIG_H
25# include "config.h"
26#endif
27
28#include "mutt.h"
29#include "copy.h"
30#include "mailbox.h"
31#include "mx.h"
32
33#include <sys/stat.h>
34#include <errno.h>
35
36#include <time.h>
37
38/*
39 * return value:
40 *
41 * 1 message not modified
42 * 0 message edited successfully
43 * -1 error
44 */
45
46static int edit_one_message (CONTEXT *ctx, HEADER *cur)
47{
48 BUFFER *tmp = NULL;
49 char buff[STRING];
50 int omagic;
51 int oerrno;
52 int rc;
53
54 unsigned short o_read;
55 unsigned short o_old;
56
57 int of, cf;
58
59 CONTEXT tmpctx;
60 MESSAGE *msg;
61
62 FILE *fp = NULL;
63
64 struct stat sb;
65 time_t mtime = 0;
66
67 tmp = mutt_buffer_pool_get ();
68 mutt_buffer_mktemp (tmp);
69
70 omagic = DefaultMagic;
71 DefaultMagic = MUTT_MBOX;
72
73 rc = (mx_open_mailbox (mutt_b2s (tmp), MUTT_NEWFOLDER, &tmpctx) == NULL) ? -1 : 0;
74
75 DefaultMagic = omagic;
76
77 if (rc == -1)
78 {
79 mutt_error (_("could not create temporary folder: %s"), strerror (errno));
80 mutt_buffer_pool_release (&tmp);
81 return -1;
82 }
83
84 rc = mutt_append_message (&tmpctx, ctx, cur, 0, CH_NOLEN |
85 ((ctx->magic == MUTT_MBOX || ctx->magic == MUTT_MMDF) ? 0 : CH_NOSTATUS));
86 oerrno = errno;
87
88 mx_close_mailbox (&tmpctx, NULL);
89
90 if (rc == -1)
91 {
92 mutt_error (_("could not write temporary mail folder: %s"), strerror (oerrno));
93 goto bail;
94 }
95
96 if ((rc = stat (mutt_b2s (tmp), &sb)) == -1)
97 {
98 mutt_error (_("Can't stat %s: %s"), mutt_b2s (tmp), strerror (errno));
99 goto bail;
100 }
101
102 /*
103 * 2002-09-05 me@sigpipe.org
104 * The file the user is going to edit is not a real mbox, so we need to
105 * truncate the last newline in the temp file, which is logically part of
106 * the message separator, and not the body of the message. If we fail to
107 * remove it, the message will grow by one line each time the user edits
108 * the message.
109 */
110 if (sb.st_size != 0 &&
111 truncate (mutt_b2s (tmp), sb.st_size - 1) == -1)
112 {
113 mutt_error (_("could not truncate temporary mail folder: %s"),
114 strerror (errno));
115 goto bail;
116 }
117
118 mtime = mutt_decrease_mtime (mutt_b2s (tmp), &sb);
119
120 mutt_edit_file (NONULL(Editor), mutt_b2s (tmp));
121
122 if ((rc = stat (mutt_b2s (tmp), &sb)) == -1)
123 {
124 mutt_error (_("Can't stat %s: %s"), mutt_b2s (tmp), strerror (errno));
125 goto bail;
126 }
127
128 if (sb.st_size == 0)
129 {
130 mutt_message (_("Message file is empty!"));
131 rc = 1;
132 goto bail;
133 }
134
135 if (sb.st_mtime == mtime)
136 {
137 mutt_message (_("Message not modified!"));
138 rc = 1;
139 goto bail;
140 }
141
142 if ((fp = fopen (mutt_b2s (tmp), "r")) == NULL)
143 {
144 rc = -1;
145 mutt_error (_("Can't open message file: %s"), strerror (errno));
146 goto bail;
147 }
148
149 if (mx_open_mailbox (ctx->path, MUTT_APPEND, &tmpctx) == NULL)
150 {
151 rc = -1;
152 /* L10N: %s is from strerror(errno) */
153 mutt_error (_("Can't append to folder: %s"), strerror (errno));
154 goto bail;
155 }
156
157 of = 0;
158 cf = ((tmpctx.magic == MUTT_MBOX || tmpctx.magic == MUTT_MMDF) ? 0 : CH_NOSTATUS);
159
160 if (fgets (buff, sizeof (buff), fp) && is_from (buff, NULL, 0, NULL))
161 {
162 if (tmpctx.magic == MUTT_MBOX || tmpctx.magic == MUTT_MMDF)
163 cf = CH_FROM | CH_FORCE_FROM;
164 }
165 else
166 of = MUTT_ADD_FROM;
167
168 /*
169 * XXX - we have to play games with the message flags to avoid
170 * problematic behavior with maildir folders.
171 *
172 */
173
174 o_read = cur->read; o_old = cur->old;
175 cur->read = cur->old = 0;
176 msg = mx_open_new_message (&tmpctx, cur, of);
177 cur->read = o_read; cur->old = o_old;
178
179 if (msg == NULL)
180 {
181 mutt_error (_("Can't append to folder: %s"), strerror (errno));
182 mx_close_mailbox (&tmpctx, NULL);
183 goto bail;
184 }
185
186 if ((rc = mutt_copy_hdr (fp, msg->fp, 0, sb.st_size, CH_NOLEN | cf, NULL)) == 0)
187 {
188 fputc ('\n', msg->fp);
189 rc = mutt_copy_stream (fp, msg->fp);
190 }
191
192 rc = mx_commit_message (msg, &tmpctx);
193 mx_close_message (&tmpctx, &msg);
194
195 mx_close_mailbox (&tmpctx, NULL);
196
197bail:
198 if (fp) safe_fclose (&fp);
199
200 if (rc >= 0)
201 unlink (mutt_b2s (tmp));
202
203 if (rc == 0)
204 {
205 mutt_set_flag (Context, cur, MUTT_DELETE, 1);
206 mutt_set_flag (Context, cur, MUTT_PURGE, 1);
207 mutt_set_flag (Context, cur, MUTT_READ, 1);
208
209 if (option (OPTDELETEUNTAG))
210 mutt_set_flag (Context, cur, MUTT_TAG, 0);
211 }
212 else if (rc == -1)
213 mutt_message (_("Error. Preserving temporary file: %s"), mutt_b2s (tmp));
214
215 mutt_buffer_pool_release (&tmp);
216
217 return rc;
218}
219
220int mutt_edit_message (CONTEXT *ctx, HEADER *hdr)
221{
222 int i, j;
223
224 if (hdr)
225 return edit_one_message (ctx, hdr);
226
227
228 for (i = 0; i < ctx->vcount; i++)
229 {
230 j = ctx->v2r[i];
231 if (ctx->hdrs[j]->tagged)
232 {
233 if (edit_one_message (ctx, ctx->hdrs[j]) == -1)
234 return -1;
235 }
236 }
237
238 return 0;
239}