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 char tmp[_POSIX_PATH_MAX];
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 mutt_mktemp (tmp, sizeof (tmp));
68
69 omagic = DefaultMagic;
70 DefaultMagic = MUTT_MBOX;
71
72 rc = (mx_open_mailbox (tmp, MUTT_NEWFOLDER, &tmpctx) == NULL) ? -1 : 0;
73
74 DefaultMagic = omagic;
75
76 if (rc == -1)
77 {
78 mutt_error (_("could not create temporary folder: %s"), strerror (errno));
79 return -1;
80 }
81
82 rc = mutt_append_message (&tmpctx, ctx, cur, 0, CH_NOLEN |
83 ((ctx->magic == MUTT_MBOX || ctx->magic == MUTT_MMDF) ? 0 : CH_NOSTATUS));
84 oerrno = errno;
85
86 mx_close_mailbox (&tmpctx, NULL);
87
88 if (rc == -1)
89 {
90 mutt_error (_("could not write temporary mail folder: %s"), strerror (oerrno));
91 goto bail;
92 }
93
94 if ((rc = stat (tmp, &sb)) == -1)
95 {
96 mutt_error (_("Can't stat %s: %s"), tmp, strerror (errno));
97 goto bail;
98 }
99
100 /*
101 * 2002-09-05 me@sigpipe.org
102 * The file the user is going to edit is not a real mbox, so we need to
103 * truncate the last newline in the temp file, which is logically part of
104 * the message separator, and not the body of the message. If we fail to
105 * remove it, the message will grow by one line each time the user edits
106 * the message.
107 */
108 if (sb.st_size != 0 && truncate (tmp, sb.st_size - 1) == -1)
109 {
110 mutt_error (_("could not truncate temporary mail folder: %s"),
111 strerror (errno));
112 goto bail;
113 }
114
115 mtime = mutt_decrease_mtime (tmp, &sb);
116
117 mutt_edit_file (NONULL(Editor), tmp);
118
119 if ((rc = stat (tmp, &sb)) == -1)
120 {
121 mutt_error (_("Can't stat %s: %s"), tmp, strerror (errno));
122 goto bail;
123 }
124
125 if (sb.st_size == 0)
126 {
127 mutt_message (_("Message file is empty!"));
128 rc = 1;
129 goto bail;
130 }
131
132 if (sb.st_mtime == mtime)
133 {
134 mutt_message (_("Message not modified!"));
135 rc = 1;
136 goto bail;
137 }
138
139 if ((fp = fopen (tmp, "r")) == NULL)
140 {
141 rc = -1;
142 mutt_error (_("Can't open message file: %s"), strerror (errno));
143 goto bail;
144 }
145
146 if (mx_open_mailbox (ctx->path, MUTT_APPEND, &tmpctx) == NULL)
147 {
148 rc = -1;
149 /* L10N: %s is from strerror(errno) */
150 mutt_error (_("Can't append to folder: %s"), strerror (errno));
151 goto bail;
152 }
153
154 of = 0;
155 cf = ((tmpctx.magic == MUTT_MBOX || tmpctx.magic == MUTT_MMDF) ? 0 : CH_NOSTATUS);
156
157 if (fgets (buff, sizeof (buff), fp) && is_from (buff, NULL, 0, NULL))
158 {
159 if (tmpctx.magic == MUTT_MBOX || tmpctx.magic == MUTT_MMDF)
160 cf = CH_FROM | CH_FORCE_FROM;
161 }
162 else
163 of = MUTT_ADD_FROM;
164
165 /*
166 * XXX - we have to play games with the message flags to avoid
167 * problematic behavior with maildir folders.
168 *
169 */
170
171 o_read = cur->read; o_old = cur->old;
172 cur->read = cur->old = 0;
173 msg = mx_open_new_message (&tmpctx, cur, of);
174 cur->read = o_read; cur->old = o_old;
175
176 if (msg == NULL)
177 {
178 mutt_error (_("Can't append to folder: %s"), strerror (errno));
179 mx_close_mailbox (&tmpctx, NULL);
180 goto bail;
181 }
182
183 if ((rc = mutt_copy_hdr (fp, msg->fp, 0, sb.st_size, CH_NOLEN | cf, NULL)) == 0)
184 {
185 fputc ('\n', msg->fp);
186 rc = mutt_copy_stream (fp, msg->fp);
187 }
188
189 rc = mx_commit_message (msg, &tmpctx);
190 mx_close_message (&tmpctx, &msg);
191
192 mx_close_mailbox (&tmpctx, NULL);
193
194 bail:
195 if (fp) safe_fclose (&fp);
196
197 if (rc >= 0)
198 unlink (tmp);
199
200 if (rc == 0)
201 {
202 mutt_set_flag (Context, cur, MUTT_DELETE, 1);
203 mutt_set_flag (Context, cur, MUTT_PURGE, 1);
204 mutt_set_flag (Context, cur, MUTT_READ, 1);
205
206 if (option (OPTDELETEUNTAG))
207 mutt_set_flag (Context, cur, MUTT_TAG, 0);
208 }
209 else if (rc == -1)
210 mutt_message (_("Error. Preserving temporary file: %s"), tmp);
211
212
213 return rc;
214}
215
216int mutt_edit_message (CONTEXT *ctx, HEADER *hdr)
217{
218 int i, j;
219
220 if (hdr)
221 return edit_one_message (ctx, hdr);
222
223
224 for (i = 0; i < ctx->vcount; i++)
225 {
226 j = ctx->v2r[i];
227 if (ctx->hdrs[j]->tagged)
228 {
229 if (edit_one_message (ctx, ctx->hdrs[j]) == -1)
230 return -1;
231 }
232 }
233
234 return 0;
235}