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