[PATCH 1 of 4] Create mutt_write_postponed, de-bastardize mutt_write_fcc
# HG changeset patch
# User Aron Griffis <agriffis@xxxxxxxxx>
# Date 1240931848 14400
# Branch HEAD
# Node ID bffd60d2ac16fbc99be35a1b8bf51b6ce5ac36d4
# Parent 962bfe47cc13a06cce194fe79c35ac20f9ed7591
Create mutt_write_postponed, de-bastardize mutt_write_fcc
This patch breaks the postponement code out of mutt_write_fcc. To
prevent duplicating lots of code between the functions, there are
a couple of new static functions: mutt_start_message and
mutt_finish_message.
In the process, a few bugs are fixed:
* Calculate lines and content-length prior to mx_open_new_message.
That way the error path doesn't have to abort a partly written
message, removing this questionable line of code:
mx_commit_message (msg, &f); /* XXX - really? */
* Call set_noconv_flags in the error path of mutt_write_postponed.
Previously it was only called in the success path.
* Don't write "Status: RO" on postponed messages.
Signed-off-by: Aron Griffis <agriffis@xxxxxxxxx>
diff -r 962bfe47cc13 -r bffd60d2ac16 compose.c
--- a/compose.c Mon Apr 27 18:53:40 2009 -0400
+++ b/compose.c Tue Apr 28 11:17:28 2009 -0400
@@ -1206,7 +1206,7 @@
if (msg->content->next)
msg->content = mutt_make_multipart (msg->content);
- if (mutt_write_fcc (fname, msg, NULL, 1, NULL) < 0)
+ if (mutt_write_fcc (fname, msg) < 0)
msg->content = mutt_remove_multipart (msg->content);
else
mutt_message _("Message written.");
diff -r 962bfe47cc13 -r bffd60d2ac16 protos.h
--- a/protos.h Mon Apr 27 18:53:40 2009 -0400
+++ b/protos.h Tue Apr 28 11:17:28 2009 -0400
@@ -368,7 +368,8 @@
void mutt_update_num_postponed (void);
int mutt_wait_filter (pid_t);
int mutt_which_case (const char *);
-int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int,
char *);
+int mutt_write_fcc (const char *path, HEADER *hdr);
+int mutt_write_postponed (const char *path, HEADER *hdr, const char *msgid,
char *fcc);
int mutt_write_mime_body (BODY *, FILE *);
int mutt_write_mime_header (BODY *, FILE *);
int mutt_write_one_header (FILE *fp, const char *tag, const char *value, const
char *pfx, int wraplen);
diff -r 962bfe47cc13 -r bffd60d2ac16 send.c
--- a/send.c Mon Apr 27 18:53:40 2009 -0400
+++ b/send.c Tue Apr 28 11:17:28 2009 -0400
@@ -1515,7 +1515,7 @@
mutt_prepare_envelope (msg->env, 0);
mutt_env_to_idna (msg->env, NULL, NULL); /* Handle bad IDNAs the next
time. */
- if (!Postponed || mutt_write_fcc (NONULL (Postponed), msg, (cur &&
(flags & SENDREPLY)) ? cur->env->message_id : NULL, 1, fcc) < 0)
+ if (!Postponed || mutt_write_postponed (NONULL (Postponed), msg, (cur &&
(flags & SENDREPLY)) ? cur->env->message_id : NULL, fcc) < 0)
{
msg->content = mutt_remove_multipart (msg->content);
decode_descriptions (msg->content);
@@ -1695,7 +1695,7 @@
* message was first postponed.
*/
msg->received = time (NULL);
- if (mutt_write_fcc (fcc, msg, NULL, 0, NULL) == -1)
+ if (mutt_write_fcc (fcc, msg) == -1)
{
/*
* Error writing FCC, we should abort sending.
diff -r 962bfe47cc13 -r bffd60d2ac16 sendlib.c
--- a/sendlib.c Mon Apr 27 18:53:40 2009 -0400
+++ b/sendlib.c Tue Apr 28 11:17:28 2009 -0400
@@ -2317,6 +2317,165 @@
rfc2047_decode (&env->x_label);
}
+static int count_length_lines (FILE *fp, LOFF_T *content_lengthp, int *linesp)
+{
+ char sasha[LONG_STRING];
+ int lines = 0;
+
+ /* count the number of lines */
+ while (fgets (sasha, sizeof (sasha), fp) != NULL)
+ lines++;
+ if (ferror (fp))
+ return -1;
+
+ *linesp = lines;
+ *content_lengthp = (LOFF_T) ftello (fp);
+
+ return 0;
+}
+
+/* state maintained between mutt_start_message and
+ * mutt_finish_message, opaque to callers.
+ */
+struct mutt_message_handle
+{
+ FILE *tempfp;
+ char tempfile[_POSIX_PATH_MAX];
+ LOFF_T content_length;
+ int lines;
+ struct stat st;
+ int passthru;
+};
+
+static struct mutt_message_handle *
+mutt_start_message (const char *path, HEADER *hdr,
+ CONTEXT *ctxp, MESSAGE **msgp, int passthru)
+{
+ struct mutt_message_handle *mh;
+
+ if (mx_open_mailbox (path, M_APPEND | M_QUIET, ctxp) == NULL)
+ {
+ dprint (1, (debugfile, "mutt_start_message: unable to open mailbox %s"
+ "in append-mode, aborting.\n", path));
+ return NULL;
+ }
+
+ mh = safe_calloc (1, sizeof (*mh));
+ mh->passthru = passthru;
+
+ if (ctxp->magic == M_MMDF || ctxp->magic == M_MBOX)
+ {
+ /* remember new mail status before appending message */
+ stat (path, &mh->st);
+
+ if (!passthru) {
+ /* need to add a Content-Length field to avoid problems
+ * where a line in the message body begins with "From "
+ */
+ mutt_mktemp (mh->tempfile);
+ mh->tempfp = safe_fopen (mh->tempfile, "w+");
+ if (!mh->tempfp)
+ {
+ mutt_perror (mh->tempfile);
+ dprint (1, (debugfile, "mutt_start_message: failed "
+ "to open tempfile, aborting.\n"));
+ goto error_out;
+ }
+
+ mutt_write_mime_body (hdr->content, mh->tempfp);
+
+ /* make sure the last line ends with a newline. Emacs doesn't ensure
+ * this will happen, and it can cause problems parsing the mailbox
+ * later.
+ */
+ fseek (mh->tempfp, -1, 2);
+ if (fgetc (mh->tempfp) != '\n')
+ {
+ fseek (mh->tempfp, 0, 2);
+ fputc ('\n', mh->tempfp);
+ }
+ if (fflush (mh->tempfp) || ferror (mh->tempfp))
+ {
+ dprint (1, (debugfile, "mutt_start_message: failed "
+ "to write tempfile, aborting.\n"));
+ goto error_out;
+ }
+
+ rewind (mh->tempfp);
+
+ if (count_length_lines (mh->tempfp, &mh->content_length, &mh->lines))
+ {
+ mutt_perror (mh->tempfile);
+ dprint (1, (debugfile, "mutt_start_message: failed "
+ "to count message length, aborting.\n"));
+ goto error_out;
+ }
+ }
+ }
+
+ if ((*msgp = mx_open_new_message (ctxp, hdr, M_ADD_FROM)) == NULL)
+ {
+ dprint (1, (debugfile, "mutt_start_message: mx_open_new_message "
+ "failed in %s, aborting.\n", path));
+ goto error_out;
+ }
+ return mh;
+
+error_out:
+ /* error message already provided, just clean up */
+ if (mh->tempfp)
+ {
+ safe_fclose (&mh->tempfp);
+ unlink (mh->tempfile);
+ }
+ FREE (&mh);
+ mx_close_mailbox (ctxp, NULL);
+ return NULL;
+}
+
+static int mutt_finish_message (struct mutt_message_handle *mh,
+ const char *path, HEADER *hdr,
+ CONTEXT *ctxp, MESSAGE **msgp, int skip_buffy)
+{
+ int ret = 0;
+
+ if (mh->tempfp)
+ {
+ fprintf ((*msgp)->fp, "Content-Length: " OFF_T_FMT "\n",
mh->content_length);
+ fprintf ((*msgp)->fp, "Lines: %d\n\n", mh->lines); /* NOTE double newline
*/
+
+ /* copy the body */
+ rewind (mh->tempfp);
+ ret = mutt_copy_stream (mh->tempfp, (*msgp)->fp);
+ if (safe_fclose (&mh->tempfp))
+ ret = -1;
+
+ /* if there was an error, leave the temp version */
+ if (!ret)
+ unlink (mh->tempfile);
+ }
+ else
+ {
+ if (!mh->passthru)
+ {
+ fputc ('\n', (*msgp)->fp); /* finish off the header */
+ ret = mutt_write_mime_body (hdr->content, (*msgp)->fp);
+ }
+ skip_buffy = 1; /* only needed for file-based mailboxes */
+ }
+
+ ret |= mx_commit_message (*msgp, ctxp);
+ mx_close_message (msgp);
+ mx_close_mailbox (ctxp, NULL);
+
+ if (!skip_buffy)
+ mutt_buffy_cleanup (path, &mh->st);
+
+ FREE (&mh);
+
+ return ret;
+}
+
static int _mutt_bounce_message (FILE *fp, HEADER *h, ADDRESS *to, const char
*resent_from,
ADDRESS *env_from)
{
@@ -2478,75 +2637,60 @@
}
}
-int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int
post, char *fcc)
+int mutt_write_fcc (const char *path, HEADER *hdr)
{
+ struct mutt_message_handle *mh;
CONTEXT f;
MESSAGE *msg;
- char tempfile[_POSIX_PATH_MAX];
- FILE *tempfp = NULL;
- int r, need_buffy_cleanup = 0;
- struct stat st;
- if (post)
- set_noconv_flags (hdr->content, 1);
-
- if (mx_open_mailbox (path, M_APPEND | M_QUIET, &f) == NULL)
+ hdr->read = 1; /* make sure to put it in the `cur' directory (maildir) */
+
+ mh = mutt_start_message (path, hdr, &f, &msg, 0);
+ if (!mh)
+ return -1;
+
+ mutt_write_rfc822_header (msg->fp, hdr->env, hdr->content, 0, 0);
+ fprintf (msg->fp, "Status: RO\n");
+
+ return mutt_finish_message (mh, path, hdr, &f, &msg, 0);
+}
+
+int mutt_write_postponed (const char *path, HEADER *hdr, const char *msgid,
char *fcc)
+{
+ struct mutt_message_handle *mh;
+ CONTEXT f;
+ MESSAGE *msg;
+ int ret;
+
+ hdr->read = 0; /* make sure to put it in the `new' directory (maildir) */
+ set_noconv_flags (hdr->content, 1);
+
+ mh = mutt_start_message (path, hdr, &f, &msg, 0);
+ if (!mh)
{
- dprint (1, (debugfile, "mutt_write_fcc(): unable to open mailbox %s in
append-mode, aborting.\n",
- path));
- return (-1);
+ set_noconv_flags (hdr->content, 0);
+ return -1;
}
- /* We need to add a Content-Length field to avoid problems where a line in
- * the message body begins with "From "
- */
- if (f.magic == M_MMDF || f.magic == M_MBOX)
- {
- mutt_mktemp (tempfile);
- if ((tempfp = safe_fopen (tempfile, "w+")) == NULL)
- {
- mutt_perror (tempfile);
- mx_close_mailbox (&f, NULL);
- return (-1);
- }
- /* remember new mail status before appending message */
- need_buffy_cleanup = 1;
- stat (path, &st);
- }
+ mutt_write_rfc822_header (msg->fp, hdr->env, hdr->content, -1, 0);
- hdr->read = !post; /* make sure to put it in the `cur' directory (maildir) */
- if ((msg = mx_open_new_message (&f, hdr, M_ADD_FROM)) == NULL)
- {
- mx_close_mailbox (&f, NULL);
- return (-1);
- }
-
- /* post == 1 => postpone message. Set mode = -1 in mutt_write_rfc822_header()
- * post == 0 => Normal mode. Set mode = 0 in mutt_write_rfc822_header()
- * */
- mutt_write_rfc822_header (msg->fp, hdr->env, hdr->content, post ? -post : 0,
0);
-
- /* (postponment) if this was a reply of some sort, <msgid> contians the
+ /* if this was a reply of some sort, <msgid> contains the
* Message-ID: of message replied to. Save it using a special X-Mutt-
* header so it can be picked up if the message is recalled at a later
* point in time. This will allow the message to be marked as replied if
* the same mailbox is still open.
*/
- if (post && msgid)
+ if (msgid)
fprintf (msg->fp, "X-Mutt-References: %s\n", msgid);
- /* (postponment) save the Fcc: using a special X-Mutt- header so that
+ /* save the Fcc: using a special X-Mutt- header so that
* it can be picked up when the message is recalled
*/
- if (post && fcc)
+ if (fcc)
fprintf (msg->fp, "X-Mutt-Fcc: %s\n", fcc);
- fprintf (msg->fp, "Status: RO\n");
-
-
- /* (postponment) if the mail is to be signed or encrypted, save this info */
- if ((WithCrypto & APPLICATION_PGP)
- && post && (hdr->security & APPLICATION_PGP))
+ /* if the mail is to be signed or encrypted, save this info */
+ if ((WithCrypto & APPLICATION_PGP) && (hdr->security & APPLICATION_PGP))
{
fputs ("X-Mutt-PGP: ", msg->fp);
if (hdr->security & ENCRYPT)
@@ -2562,9 +2706,8 @@
fputc ('\n', msg->fp);
}
- /* (postponment) if the mail is to be signed or encrypted, save this info */
- if ((WithCrypto & APPLICATION_SMIME)
- && post && (hdr->security & APPLICATION_SMIME))
+ /* if the mail is to be signed or encrypted, save this info */
+ if ((WithCrypto & APPLICATION_SMIME) && (hdr->security & APPLICATION_SMIME))
{
fputs ("X-Mutt-SMIME: ", msg->fp);
if (hdr->security & ENCRYPT) {
@@ -2583,84 +2726,20 @@
}
#ifdef MIXMASTER
- /* (postponement) if the mail is to be sent through a mixmaster
+ /* if the mail is to be sent through a mixmaster
* chain, save that information
*/
-
- if (post && hdr->chain && hdr->chain)
+ if (hdr->chain)
{
LIST *p;
-
fputs ("X-Mutt-Mix:", msg->fp);
for (p = hdr->chain; p; p = p->next)
fprintf (msg->fp, " %s", (char *) p->data);
-
fputc ('\n', msg->fp);
}
#endif
- if (tempfp)
- {
- char sasha[LONG_STRING];
- int lines = 0;
-
- mutt_write_mime_body (hdr->content, tempfp);
-
- /* make sure the last line ends with a newline. Emacs doesn't ensure
- * this will happen, and it can cause problems parsing the mailbox
- * later.
- */
- fseek (tempfp, -1, 2);
- if (fgetc (tempfp) != '\n')
- {
- fseek (tempfp, 0, 2);
- fputc ('\n', tempfp);
- }
-
- fflush (tempfp);
- if (ferror (tempfp))
- {
- dprint (1, (debugfile, "mutt_write_fcc(): %s: write failed.\n",
tempfile));
- safe_fclose (&tempfp);
- unlink (tempfile);
- mx_commit_message (msg, &f); /* XXX - really? */
- mx_close_message (&msg);
- mx_close_mailbox (&f, NULL);
- return -1;
- }
-
- /* count the number of lines */
- rewind (tempfp);
- while (fgets (sasha, sizeof (sasha), tempfp) != NULL)
- lines++;
- fprintf (msg->fp, "Content-Length: " OFF_T_FMT "\n", (LOFF_T) ftello
(tempfp));
- fprintf (msg->fp, "Lines: %d\n\n", lines);
-
- /* copy the body and clean up */
- rewind (tempfp);
- r = mutt_copy_stream (tempfp, msg->fp);
- if (fclose (tempfp) != 0)
- r = -1;
- /* if there was an error, leave the temp version */
- if (!r)
- unlink (tempfile);
- }
- else
- {
- fputc ('\n', msg->fp); /* finish off the header */
- r = mutt_write_mime_body (hdr->content, msg->fp);
- }
-
- if (mx_commit_message (msg, &f) != 0)
- r = -1;
- mx_close_message (&msg);
- mx_close_mailbox (&f, NULL);
-
- if (!post && need_buffy_cleanup)
- mutt_buffy_cleanup (path, &st);
-
- if (post)
- set_noconv_flags (hdr->content, 0);
-
- return r;
+ ret = mutt_finish_message (mh, path, hdr, &f, &msg, 0);
+ set_noconv_flags (hdr->content, 0);
+ return ret;
}