mutt stable branch with some hacks
at jcs 239 lines 5.6 kB view raw
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}