#include "mailbox.h"
#include "sort.h"
#include "charset.h"
+#include "rfc3676.h"
#ifdef MIXMASTER
#include "remailer.h"
case OP_COMPOSE_EDIT_MESSAGE:
if (Editor && (mutt_strcmp ("builtin", Editor) != 0) && !option (OPTEDITHDRS))
{
+ mutt_rfc3676_space_unstuff (msg);
mutt_edit_file (Editor, msg->content->filename);
+ mutt_rfc3676_space_stuff (msg);
mutt_update_encoding (msg->content);
menu->redraw = REDRAW_FULL;
mutt_message_hook (NULL, msg, MUTT_SEND2HOOK);
}
/* fall through */
case OP_COMPOSE_EDIT_HEADERS:
+ mutt_rfc3676_space_unstuff (msg);
+
if (mutt_strcmp ("builtin", Editor) != 0 &&
(op == OP_COMPOSE_EDIT_HEADERS ||
(op == OP_COMPOSE_EDIT_MESSAGE && option (OPTEDITHDRS))))
code below to regenerate the index array */
mutt_builtin_editor (msg->content->filename, msg, cur);
}
+
+ mutt_rfc3676_space_stuff (msg);
mutt_update_encoding (msg->content);
/* attachments may have been added */
#include "mutt_curses.h"
#include "ascii.h"
#include "lib.h"
+#include "mime.h"
#define FLOWED_MAX 72
* certain lines:
* - lines starting with a space
* - lines starting with 'From '
- * This routine is only called once right after editing the
- * initial message so it's up to the user to take care of stuffing
- * when editing the message several times before actually sending it
*
- * This is more or less a hack as it replaces the message's content with
- * a freshly created copy in a tempfile and modifies the file's mtime
- * so we don't trigger code paths watching for mtime changes
+ * Care is taken to preserve the hdr->content->filename, as
+ * mutt -i -E can directly edit a passed in filename.
*/
-void rfc3676_space_stuff (HEADER* hdr)
+static void rfc3676_space_stuff (HEADER* hdr)
{
-#if DEBUG
- int lc = 0;
- size_t len = 0;
- unsigned char c = '\0';
-#endif
FILE *in = NULL, *out = NULL;
- char buf[LONG_STRING];
- char tmpfile[_POSIX_PATH_MAX];
+ char *buf = NULL;
+ size_t blen = 0;
+ BUFFER *tmpfile = NULL;
- if (!hdr || !hdr->content || !hdr->content->filename)
- return;
-
- dprint (2, (debugfile, "f=f: postprocess %s\n", hdr->content->filename));
+ tmpfile = mutt_buffer_pool_get ();
if ((in = safe_fopen (hdr->content->filename, "r")) == NULL)
- return;
+ goto bail;
- mutt_mktemp (tmpfile, sizeof (tmpfile));
- if ((out = safe_fopen (tmpfile, "w+")) == NULL)
- {
- safe_fclose (&in);
- return;
- }
+ mutt_buffer_mktemp (tmpfile);
+ if ((out = safe_fopen (mutt_b2s (tmpfile), "w+")) == NULL)
+ goto bail;
- while (fgets (buf, sizeof (buf), in))
+ while ((buf = mutt_read_line (buf, &blen, in, NULL, 0)) != NULL)
{
if (ascii_strncmp ("From ", buf, 5) == 0 || buf[0] == ' ')
- {
fputc (' ', out);
-#if DEBUG
- lc++;
- len = mutt_strlen (buf);
- if (len > 0)
- {
- c = buf[len-1];
- buf[len-1] = '\0';
- }
- dprint (4, (debugfile, "f=f: line %d needs space-stuffing: '%s'\n",
- lc, buf));
- if (len > 0)
- buf[len-1] = c;
-#endif
- }
fputs (buf, out);
+ fputc ('\n', out);
+ }
+ FREE (&buf);
+ safe_fclose (&in);
+ safe_fclose (&out);
+ mutt_set_mtime (hdr->content->filename, mutt_b2s (tmpfile));
+
+ if ((in = safe_fopen (mutt_b2s (tmpfile), "r")) == NULL)
+ goto bail;
+
+ if ((truncate (hdr->content->filename, 0) == -1) ||
+ ((out = safe_fopen (hdr->content->filename, "a")) == NULL))
+ {
+ goto bail;
+ }
+
+ mutt_copy_stream (in, out);
+ safe_fclose (&in);
+ safe_fclose (&out);
+ mutt_set_mtime (mutt_b2s (tmpfile), hdr->content->filename);
+ unlink (mutt_b2s (tmpfile));
+ mutt_buffer_pool_release (&tmpfile);
+ return;
+
+bail:
+ safe_fclose (&in);
+ safe_fclose (&out);
+ mutt_buffer_pool_release (&tmpfile);
+}
+
+static void rfc3676_space_unstuff (HEADER* hdr)
+{
+ FILE *in = NULL, *out = NULL;
+ char *buf = NULL;
+ size_t blen = 0;
+ BUFFER *tmpfile = NULL;
+
+ tmpfile = mutt_buffer_pool_get ();
+
+ if ((in = safe_fopen (hdr->content->filename, "r")) == NULL)
+ goto bail;
+
+ mutt_buffer_mktemp (tmpfile);
+ if ((out = safe_fopen (mutt_b2s (tmpfile), "w+")) == NULL)
+ goto bail;
+
+ while ((buf = mutt_read_line (buf, &blen, in, NULL, 0)) != NULL)
+ {
+ if (buf[0] == ' ')
+ fputs (buf + 1, out);
+ else
+ fputs (buf, out);
+ fputc ('\n', out);
}
+ FREE (&buf);
safe_fclose (&in);
safe_fclose (&out);
- mutt_set_mtime (hdr->content->filename, tmpfile);
- unlink (hdr->content->filename);
- mutt_str_replace (&hdr->content->filename, tmpfile);
+ mutt_set_mtime (hdr->content->filename, mutt_b2s (tmpfile));
+
+ if ((in = safe_fopen (mutt_b2s (tmpfile), "r")) == NULL)
+ goto bail;
+
+ if ((truncate (hdr->content->filename, 0) == -1) ||
+ ((out = safe_fopen (hdr->content->filename, "a")) == NULL))
+ {
+ goto bail;
+ }
+
+ mutt_copy_stream (in, out);
+ safe_fclose (&in);
+ safe_fclose (&out);
+ mutt_set_mtime (mutt_b2s (tmpfile), hdr->content->filename);
+ unlink (mutt_b2s (tmpfile));
+ mutt_buffer_pool_release (&tmpfile);
+ return;
+
+bail:
+ safe_fclose (&in);
+ safe_fclose (&out);
+ mutt_buffer_pool_release (&tmpfile);
+}
+
+/* Note: we don't check the option OPTTEXTFLOWED because we want to
+ * stuff based the actual content type. The option only decides
+ * whether to *set* format=flowed on new messages.
+ */
+void mutt_rfc3676_space_stuff (HEADER *hdr)
+{
+ const char *format;
+
+ if (!hdr || !hdr->content || !hdr->content->filename)
+ return;
+
+ if (hdr->content->type == TYPETEXT &&
+ !ascii_strcasecmp ("plain", hdr->content->subtype))
+ {
+ format = mutt_get_parameter ("format", hdr->content->parameter);
+ if (!ascii_strcasecmp ("flowed", format))
+ rfc3676_space_stuff (hdr);
+ }
+}
+
+void mutt_rfc3676_space_unstuff (HEADER *hdr)
+{
+ const char *format;
+
+ if (!hdr || !hdr->content || !hdr->content->filename)
+ return;
+
+ if (hdr->content->type == TYPETEXT &&
+ !ascii_strcasecmp ("plain", hdr->content->subtype))
+ {
+ format = mutt_get_parameter ("format", hdr->content->parameter);
+ if (!ascii_strcasecmp ("flowed", format))
+ rfc3676_space_unstuff (hdr);
+ }
}
*/
msg->replied = 0;
- if (! (flags & SENDKEY))
- {
- if (option (OPTTEXTFLOWED) && msg->content->type == TYPETEXT && !ascii_strcasecmp (msg->content->subtype, "plain"))
- mutt_set_parameter ("format", "flowed", &msg->content->parameter);
- }
-
/* $use_from and/or $from might have changed in a send-hook */
if (killfrom)
{
append_signature (tempfp);
}
+ /* Only set format=flowed for new messages. Postponed/resent/draftfiles
+ * should respect the original email.
+ *
+ * This is set here so that send-hook can be used to turn the option on.
+ */
+ if (!(flags & (SENDKEY | SENDPOSTPONED | SENDRESEND | SENDDRAFTFILE)))
+ {
+ if (option (OPTTEXTFLOWED) &&
+ msg->content->type == TYPETEXT &&
+ !ascii_strcasecmp (msg->content->subtype, "plain"))
+ mutt_set_parameter ("format", "flowed", &msg->content->parameter);
+ }
+
/*
* This hook is even called for postponed messages, and can, e.g., be
* used for setting the editor, the sendmail path, or the
mutt_perror (msg->content->filename);
}
- /* If using format=flowed, perform space stuffing. Avoid stuffing when
- * recalling a postponed message where the stuffing was already
- * performed. If it has already been performed, the format=flowed
- * parameter will be present.
- */
- if (option (OPTTEXTFLOWED) && msg->content->type == TYPETEXT && !ascii_strcasecmp("plain", msg->content->subtype))
- {
- char *p = mutt_get_parameter("format", msg->content->parameter);
- if (ascii_strcasecmp("flowed", NONULL(p)))
- rfc3676_space_stuff (msg);
- }
-
mutt_message_hook (NULL, msg, MUTT_SEND2HOOK);
}
}
+ mutt_rfc3676_space_stuff (msg);
+
mutt_update_encoding (msg->content);
if (! (flags & (SENDMAILX | SENDBATCH)))