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