From 283cc465b8a09272d2c15e33e026b1d32eb312ae Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Sun, 7 Nov 1999 22:19:45 +0000 Subject: [PATCH] Rewriting lots of the recvattach code. --- Makefile.am | 2 +- attach.c | 7 +- attach.h | 8 +- browser.c | 2 +- commands.c | 2 +- compose.c | 2 +- curs_main.c | 5 +- functions.h | 1 + init.h | 30 +- mutt.h | 2 +- muttlib.c | 107 +++++++ pager.c | 92 ++++-- pager.h | 2 + postpone.c | 36 ++- protos.h | 21 +- recvattach.c | 357 ++++----------------- recvcmd.c | 873 +++++++++++++++++++++++++++++++++++++++++++++++++++ rfc1524.c | 39 --- rfc1524.h | 1 - send.c | 235 +++++++++----- sendlib.c | 58 ++-- 21 files changed, 1369 insertions(+), 513 deletions(-) create mode 100644 recvcmd.c diff --git a/Makefile.am b/Makefile.am index 4a6f3b93..d0ff659c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -29,7 +29,7 @@ mutt_SOURCES = $(BUILT_SOURCES) \ edit.c enter.c flags.c init.c filter.c from.c getdomain.c \ handler.c hash.c hdrline.c headers.c help.c hook.c keymap.c \ main.c mbox.c menu.c mh.c mx.c pager.c parse.c pattern.c \ - postpone.c query.c recvattach.c \ + postpone.c query.c recvattach.c recvcmd.c \ rfc822.c rfc1524.c rfc2047.c rfc2231.c \ score.c send.c sendlib.c signal.c sort.c \ status.c system.c thread.c charset.c history.c lib.c \ diff --git a/attach.c b/attach.c index ea77dd04..ebc83df0 100644 --- a/attach.c +++ b/attach.c @@ -360,7 +360,8 @@ int mutt_is_autoview (BODY *b, const char *type) } /* returns -1 on error, 0 or the return code from mutt_do_pager() on success */ -int mutt_view_attachment (FILE *fp, BODY *a, int flag) +int mutt_view_attachment (FILE *fp, BODY *a, int flag, HEADER *hdr, + ATTACHPTR **idx, short idxlen) { char tempfile[_POSIX_PATH_MAX] = ""; char pagerfile[_POSIX_PATH_MAX] = ""; @@ -570,6 +571,10 @@ int mutt_view_attachment (FILE *fp, BODY *a, int flag) info.fp = fp; info.bdy = a; info.ctx = Context; + info.idx = idx; + info.idxlen = idxlen; + info.hdr = hdr; + rc = mutt_do_pager (descrip, pagerfile, is_message ? M_PAGER_MESSAGE : 0, &info); } diff --git a/attach.h b/attach.h index 32e9d0d5..dee07efb 100644 --- a/attach.h +++ b/attach.h @@ -23,4 +23,10 @@ int mutt_tag_attach (MUTTMENU *menu, int n); void mutt_save_attachment_list (FILE *fp, int tag, BODY *top, HEADER *hdr); void mutt_pipe_attachment_list (FILE *fp, int tag, BODY *top, int filter); void mutt_print_attachment_list (FILE *fp, int tag, BODY *top); -void mutt_attach_display_loop (MUTTMENU *menu, int op, FILE *fp, ATTACHPTR **idx); +void mutt_attach_display_loop (MUTTMENU *menu, int op, FILE *fp, HEADER *hdr, + ATTACHPTR **idx, short idxlen); + +void mutt_attach_bounce (FILE *, HEADER *, ATTACHPTR **, short, BODY *); +void mutt_attach_resend (FILE *, HEADER *, ATTACHPTR **, short, BODY *); +void mutt_attach_forward (FILE *, HEADER *, ATTACHPTR **, short, BODY *); +void mutt_attach_reply (FILE *, HEADER *, ATTACHPTR **, short, BODY *, int); diff --git a/browser.c b/browser.c index b51746c3..14c1089b 100644 --- a/browser.c +++ b/browser.c @@ -1030,7 +1030,7 @@ void _mutt_select_file (char *f, size_t flen, int buffy, b = mutt_make_file_attach (buf); if (b != NULL) { - mutt_view_attachment (NULL, b, M_REGULAR); + mutt_view_attachment (NULL, b, M_REGULAR, NULL, NULL, 0); mutt_free_body (&b); menu->redraw = REDRAW_FULL; } diff --git a/commands.c b/commands.c index b0ef9a6b..219d46da 100644 --- a/commands.c +++ b/commands.c @@ -227,7 +227,7 @@ void ci_bounce_message (HEADER *h, int *redraw) return; } - mutt_bounce_message (h, adr); + mutt_bounce_message (NULL, h, adr); rfc822_free_address (&adr); mutt_message (h ? _("Message bounced.") : _("Messages bounced.")); } diff --git a/compose.c b/compose.c index 3a7df737..afef5da8 100644 --- a/compose.c +++ b/compose.c @@ -1102,7 +1102,7 @@ int mutt_compose_menu (HEADER *msg, /* structure for new message */ case OP_VIEW_ATTACH: case OP_DISPLAY_HEADERS: CHECK_COUNT; - mutt_attach_display_loop (menu, op, NULL, idx); + mutt_attach_display_loop (menu, op, NULL, NULL, idx, idxlen); menu->redraw = REDRAW_FULL; mutt_clear_error (); break; diff --git a/curs_main.c b/curs_main.c index d0c99587..5bdf8a40 100644 --- a/curs_main.c +++ b/curs_main.c @@ -1676,12 +1676,11 @@ int mutt_index_menu (void) for (j = 0; j < Context->vcount; j++) { if (Context->hdrs[Context->v2r[j]]->tagged) - ci_send_message (SENDRESEND, NULL, NULL, Context, - Context->hdrs[Context->v2r[j]]); + mutt_resend_message (NULL, Context, Context->hdrs[Context->v2r[j]]); } } else - ci_send_message (SENDRESEND, NULL, NULL, Context, CURHDR); + mutt_resend_message (NULL, Context, CURHDR); menu->redraw = REDRAW_FULL; break; diff --git a/functions.h b/functions.h index 92c439e6..5bac5774 100644 --- a/functions.h +++ b/functions.h @@ -239,6 +239,7 @@ struct binding_t OpAttach[] = { { "pipe-entry", OP_PIPE, "|" }, { "view-mailcap", OP_ATTACH_VIEW_MAILCAP, "m" }, { "reply", OP_REPLY, "r" }, + { "resend-message", OP_RESEND, "\033e" }, { "group-reply", OP_GROUP_REPLY, "g" }, { "list-reply", OP_LIST_REPLY, "L" }, { "forward-message", OP_FORWARD_MESSAGE, "f" }, diff --git a/init.h b/init.h index 5e334a96..e47aedf1 100644 --- a/init.h +++ b/init.h @@ -483,28 +483,6 @@ struct option_t MuttVars[] = { ** .pp ** Also see the ``$$record'' variable. */ - { "forward_attachment", DT_BOOL, R_NONE, OPTFORWATTACH, 0 }, - /* - ** .pp - ** When set, and you (tag-)forward attachments from the Attachment menu, - ** Mutt creates a new message with the specified attachments \fIonly\fP. - ** ``$$forward_format'' is used to set the default subject. - ** .pp - ** When unset, Mutt creates a pseudo-message comprising the tagged - ** attachments and forwards that. See the section on Forwarding a message - ** for details. - ** .pp - ** For example: if you have a message containing a image/gif, - ** application/octet-stream, or whatever attachment, you can go to the - ** Attachment menu and forward ONLY that attachment to someone else. - ** .pp - ** Basically, setting this variable produces the same effect as - ** explicitly saving the attachment(s), composing a new message and then - ** attaching the saved file(s). - */ - { "forw_attachment", DT_SYN, R_NONE, UL "forward_attachment", 0 }, - /* - */ { "forward_decode", DT_BOOL, R_NONE, OPTFORWDECODE, 1 }, /* ** .pp @@ -922,6 +900,14 @@ struct option_t MuttVars[] = { /* */ + { "mime_forward_rest", DT_QUAD, R_NONE, OPT_MIMEFWDREST, M_YES }, + /* + ** .pp + ** When forwarding multiple attachments of a MIME message from the recvattach + ** menu, attachments which cannot be decoded in a reasonable manner will + ** be attached to the newly composed message if this option is set. + */ + #ifdef MIXMASTER { "mix_entry_format", DT_STR, R_NONE, UL &MixEntryFormat, UL "%4n %c %-16s %a" }, /* diff --git a/mutt.h b/mutt.h index 46e7803d..2e19ee32 100644 --- a/mutt.h +++ b/mutt.h @@ -245,6 +245,7 @@ enum OPT_ABORT, OPT_RECALL, OPT_SUBJECT, + OPT_MIMEFWDREST, OPT_MAX }; @@ -284,7 +285,6 @@ enum OPTFCCATTACH, OPTFOLLOWUPTO, OPTFORCENAME, - OPTFORWATTACH, OPTFORWDECODE, OPTFORWQUOTE, OPTHDRS, diff --git a/muttlib.c b/muttlib.c index 1b995803..ee388af2 100644 --- a/muttlib.c +++ b/muttlib.c @@ -55,6 +55,113 @@ BODY *mutt_dup_body (BODY *b) return bn; } +/* Modified by blong to accept a "suggestion" for file name. If + * that file exists, then construct one with unique name but + * keep any extension. This might fail, I guess. + * Renamed to mutt_adv_mktemp so I only have to change where it's + * called, and not all possible cases. + */ +void mutt_adv_mktemp (char *s, size_t l) +{ + char buf[_POSIX_PATH_MAX]; + char tmp[_POSIX_PATH_MAX]; + char *period; + size_t sl; + struct stat sb; + + strfcpy (buf, NONULL (Tempdir), sizeof (buf)); + mutt_expand_path (buf, sizeof (buf)); + if (s[0] == '\0') + { + snprintf (s, l, "%s/muttXXXXXX", buf); + mktemp (s); + } + else + { + strfcpy (tmp, s, sizeof (tmp)); + snprintf (s, l, "%s/%s", buf, tmp); + if (lstat (s, &sb) == -1 && errno == ENOENT) + return; + if ((period = strrchr (tmp, '.')) != NULL) + *period = 0; + snprintf (s, l, "%s/%s.XXXXXX", buf, tmp); + mktemp (s); + if (period != NULL) + { + *period = '.'; + sl = mutt_strlen(s); + strfcpy(s + sl, period, l - sl); + } + } +} + +/* create a send-mode duplicate from a receive-mode body */ + +int mutt_copy_body (FILE *fp, BODY **tgt, BODY *src) +{ + char tmp[_POSIX_PATH_MAX]; + BODY *b; + + PARAMETER *par, **ppar; + + short use_disp; + + if (src->filename) + { + use_disp = 1; + strfcpy (tmp, src->filename, sizeof (tmp)); + } + else + { + use_disp = 0; + tmp[0] = '\0'; + } + + mutt_adv_mktemp (tmp, sizeof (tmp)); + if (mutt_save_attachment (fp, src, tmp, 0, NULL) == -1) + return -1; + + *tgt = mutt_new_body (); + b = *tgt; + + memcpy (b, src, sizeof (BODY)); + b->parts = NULL; + b->next = NULL; + + b->filename = safe_strdup (tmp); + b->use_disp = use_disp; + b->unlink = 1; + + if (mutt_is_text_type (b->type, b->subtype)) + b->noconv = 1; + + /* the following code is borrowed from mutt_prepare_template (). + * Does someone have a nice function name for it, so we can re-unite + * it? + */ + + b->xtype = safe_strdup (b->xtype); + b->subtype = safe_strdup (b->subtype); + b->form_name = safe_strdup (b->form_name); + b->filename = safe_strdup (b->filename); + b->d_filename = safe_strdup (b->d_filename); + + /* copy parameters */ + for (par = b->parameter, ppar = &b->parameter; par; ppar = &(*ppar)->next, par = par->next) + { + *ppar = mutt_new_parameter (); + (*ppar)->attribute = safe_strdup (par->attribute); + (*ppar)->value = safe_strdup (par->value); + } + + mutt_stamp_attachment (b); + + return 0; + +} + + + void mutt_free_body (BODY **p) { BODY *a = *p, *b; diff --git a/pager.c b/pager.c index 03bbb635..9ac706bc 100644 --- a/pager.c +++ b/pager.c @@ -49,7 +49,10 @@ #define ISHEADER(x) ((x) == MT_COLOR_HEADER || (x) == MT_COLOR_HDEFAULT) #define IsAttach(x) (x && (x)->bdy) -#define IsHeader(x) (x && (x)->hdr) +#define IsRecvAttach(x) (x && (x)->bdy && (x)->fp) +#define IsSendAttach(x) (x && (x)->bdy && !(x)->fp) +#define IsMsgAttach(x) (x && (x)->fp && (x)->bdy && (x)->bdy->hdr) +#define IsHeader(x) (x && (x)->hdr && !(x)->bdy) static const char *Not_available_in_this_menu = N_("Not available in this menu."); static const char *Mailbox_is_read_only = N_("Mailbox is read-only."); @@ -1638,7 +1641,14 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) COLS-9 < sizeof (buffer) ? COLS-9 : sizeof (buffer), NONULL (PagerFmt), Context, extra->hdr, M_FORMAT_MAKEPRINT); } - printw ("%-*.*s -- (", COLS-10, COLS-10, IsHeader (extra) ? buffer : banner); + else if (IsMsgAttach (extra)) + { + _mutt_make_string (buffer, + COLS - 9 < sizeof (buffer) ? COLS - 9: sizeof (buffer), + NONULL (PagerFmt), Context, extra->bdy->hdr, M_FORMAT_MAKEPRINT); + } + printw ("%-*.*s -- (", COLS-10, COLS-10, + IsHeader (extra) || IsMsgAttach (extra) ? buffer : banner); if (last_pos < sb.st_size - 1) printw ("%d%%)", (int) (100 * last_offset / sb.st_size)); else @@ -2046,14 +2056,33 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) */ case OP_BOUNCE_MESSAGE: - CHECK_MODE(IsHeader (extra)); + CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra)) CHECK_ATTACH; - ci_bounce_message (extra->hdr, &redraw); + if (IsMsgAttach (extra)) + mutt_attach_bounce (extra->fp, extra->hdr, + extra->idx, extra->idxlen, + extra->bdy); + else + ci_bounce_message (extra->hdr, &redraw); break; + case OP_RESEND: + CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra)) + CHECK_ATTACH; + if (IsMsgAttach (extra)) + mutt_attach_resend (extra->fp, extra->hdr, + extra->idx, extra->idxlen, + extra->bdy); + else + mutt_resend_message (NULL, extra->ctx, extra->hdr); + break; + case OP_CREATE_ALIAS: - CHECK_MODE(IsHeader (extra)); - mutt_create_alias (extra->hdr->env, NULL); + CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra)); + if (IsMsgAttach (extra)) + mutt_create_alias (extra->bdy->hdr->env, NULL); + else + mutt_create_alias (extra->hdr->env, NULL); MAYBE_REDRAW (redraw); break; @@ -2094,8 +2123,11 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) break; case OP_DISPLAY_ADDRESS: - CHECK_MODE(IsHeader (extra)); - mutt_display_address (extra->hdr->env); + CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra)); + if (IsMsgAttach (extra)) + mutt_display_address (extra->bdy->hdr->env); + else + mutt_display_address (extra->hdr->env); break; case OP_ENTER_COMMAND: @@ -2206,21 +2238,29 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) break; case OP_PRINT: - CHECK_MODE(IsHeader (extra)); - mutt_print_message (extra->hdr); + CHECK_MODE(IsHeader (extra) || IsAttach (extra)); + if (IsAttach (extra)) + mutt_print_attachment_list (extra->fp, 0, extra->bdy); + else + mutt_print_message (extra->hdr); break; case OP_MAIL: - CHECK_MODE(IsHeader (extra)); + CHECK_MODE(IsHeader (extra) && !IsAttach (extra)); CHECK_ATTACH; ci_send_message (0, NULL, NULL, NULL, NULL); redraw = REDRAW_FULL; break; case OP_REPLY: - CHECK_MODE(IsHeader (extra)); + CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra)); CHECK_ATTACH; - ci_send_message (SENDREPLY, NULL, NULL, extra->ctx, extra->hdr); + if (IsMsgAttach (extra)) + mutt_attach_reply (extra->fp, extra->hdr, extra->idx, + extra->idxlen, extra->bdy, + SENDREPLY); + else + ci_send_message (SENDREPLY, NULL, NULL, extra->ctx, extra->hdr); redraw = REDRAW_FULL; break; @@ -2232,23 +2272,35 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) break; case OP_GROUP_REPLY: - CHECK_MODE(IsHeader (extra)); + CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra)); CHECK_ATTACH; - ci_send_message (SENDREPLY | SENDGROUPREPLY, NULL, NULL, extra->ctx, extra->hdr); + if (IsMsgAttach (extra)) + mutt_attach_reply (extra->fp, extra->hdr, extra->idx, + extra->idxlen, extra->bdy, SENDREPLY|SENDGROUPREPLY); + else + ci_send_message (SENDREPLY | SENDGROUPREPLY, NULL, NULL, extra->ctx, extra->hdr); redraw = REDRAW_FULL; break; case OP_LIST_REPLY: - CHECK_MODE(IsHeader (extra)); - CHECK_ATTACH; - ci_send_message (SENDREPLY | SENDLISTREPLY, NULL, NULL, extra->ctx, extra->hdr); + CHECK_MODE(IsHeader (extra) || IsMsgAttach (extra)); + CHECK_ATTACH; + if (IsMsgAttach (extra)) + mutt_attach_reply (extra->fp, extra->hdr, extra->idx, + extra->idxlen, extra->bdy, SENDREPLY|SENDLISTREPLY); + else + ci_send_message (SENDREPLY | SENDLISTREPLY, NULL, NULL, extra->ctx, extra->hdr); redraw = REDRAW_FULL; break; case OP_FORWARD_MESSAGE: - CHECK_MODE(IsHeader (extra)); + CHECK_MODE(IsHeader (extra) && !IsMsgAttach (extra)); CHECK_ATTACH; - ci_send_message (SENDFORWARD, NULL, NULL, extra->ctx, extra->hdr); + if (IsMsgAttach (extra)) + mutt_attach_forward (extra->fp, extra->hdr, extra->idx, + extra->idxlen, extra->bdy); + else + ci_send_message (SENDFORWARD, NULL, NULL, extra->ctx, extra->hdr); redraw = REDRAW_FULL; break; diff --git a/pager.h b/pager.h index b81d5ea5..1761ab33 100644 --- a/pager.h +++ b/pager.h @@ -38,6 +38,8 @@ typedef struct HEADER *hdr; /* current message */ BODY *bdy; /* current attachment */ FILE *fp; /* source stream */ + ATTACHPTR **idx; /* attachment information */ + short idxlen; } pager_t; int mutt_do_pager (const char *, const char *, int, pager_t *); diff --git a/postpone.c b/postpone.c index c159322d..7ad73fb7 100644 --- a/postpone.c +++ b/postpone.c @@ -282,7 +282,7 @@ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur, char *fcc, size return (-1); } - if (mutt_prepare_template (PostContext, hdr, h, 0) < 0) + if (mutt_prepare_template (NULL, PostContext, hdr, h, 0) < 0) { mx_fastclose_mailbox (PostContext); #ifdef USE_IMAP @@ -510,23 +510,31 @@ static void free_body_list (BODY **bp) } -int mutt_prepare_template (CONTEXT *ctx, HEADER *newhdr, HEADER *hdr, +int mutt_prepare_template (FILE *fp, CONTEXT *ctx, HEADER *newhdr, HEADER *hdr, short weed) { PARAMETER *par, **ppar; - MESSAGE *msg; + MESSAGE *msg = NULL; char file[_POSIX_PATH_MAX]; BODY *b; LIST *p, **q; FILE *bfp; - - if ((msg = mx_open_message (ctx, hdr->msgno)) == NULL) + + if (!fp && (msg = mx_open_message (ctx, hdr->msgno)) == NULL) return (-1); + if (!fp) fp = msg->fp; + /* parse the message header */ - fseek (msg->fp, hdr->offset, 0); - newhdr->env = mutt_read_rfc822_header (msg->fp, newhdr, 1, weed); + fseek (fp, hdr->offset, 0); + newhdr->env = mutt_read_rfc822_header (fp, newhdr, 1, weed); + + /* NOTE: We do have easy access to the entire MIME structure of + * the message to be recalled here. We could use this to + * considerably simplify the code below. + */ + mutt_free_body (&newhdr->content); /* weed user-agent, x-mailer - we don't want them here */ @@ -551,7 +559,7 @@ int mutt_prepare_template (CONTEXT *ctx, HEADER *newhdr, HEADER *hdr, safe_free ((void **) &newhdr->env->mail_followup_to); /* make sure we parse the message */ - mutt_parse_part (msg->fp, hdr->content); + mutt_parse_part (fp, hdr->content); #ifdef _PGPPATH /* decrypt pgp/mime encoded messages */ @@ -562,7 +570,7 @@ int mutt_prepare_template (CONTEXT *ctx, HEADER *newhdr, HEADER *hdr, goto err; mutt_message _("Invoking PGP..."); - if (pgp_decrypt_mime (msg->fp, &bfp, hdr->content, &b) == -1) + if (pgp_decrypt_mime (fp, &bfp, hdr->content, &b) == -1) { err: mx_close_message (&msg); @@ -594,7 +602,7 @@ int mutt_prepare_template (CONTEXT *ctx, HEADER *newhdr, HEADER *hdr, (*ppar)->value = safe_strdup (par->value); } - bfp = msg->fp; + bfp = fp; } #ifdef _PGPPATH @@ -645,8 +653,8 @@ int mutt_prepare_template (CONTEXT *ctx, HEADER *newhdr, HEADER *hdr, { mutt_free_envelope (&newhdr->env); free_body_list (&newhdr->content); - if (bfp != msg->fp) fclose (bfp); - mx_close_message (&msg); + if (bfp != fp) fclose (bfp); + if (msg) mx_close_message (&msg); return -1; } @@ -664,8 +672,8 @@ int mutt_prepare_template (CONTEXT *ctx, HEADER *newhdr, HEADER *hdr, } /* that's it. */ - if (bfp != msg->fp) fclose (bfp); - mx_close_message (&msg); + if (bfp != fp) fclose (bfp); + if (msg) mx_close_message (&msg); return 0; } diff --git a/protos.h b/protos.h index c1dd427c..8a8c2ac7 100644 --- a/protos.h +++ b/protos.h @@ -87,6 +87,8 @@ BODY *mutt_parse_multipart (FILE *, const char *, long, int); BODY *mutt_parse_messageRFC822 (FILE *, BODY *); BODY *mutt_read_mime_header (FILE *, int); +LIST *mutt_make_references(ENVELOPE *e); + ENVELOPE *mutt_read_rfc822_header (FILE *, HEADER *, short, short); HEADER *mutt_dup_header (HEADER *); @@ -123,11 +125,12 @@ char *mutt_make_date (char *, size_t); const char *mutt_fqdn(short); +void mutt_adv_mktemp (char *, size_t); void mutt_alias_menu (char *, size_t, ALIAS *); void mutt_block_signals (void); void mutt_block_signals_system (void); void mutt_body_handler (BODY *, STATE *); -void mutt_bounce_message (HEADER *, ADDRESS *); +void mutt_bounce_message (FILE *fp, HEADER *, ADDRESS *); void mutt_buffy (char *); void mutt_check_rescore (CONTEXT *); void mutt_clear_error (void); @@ -143,7 +146,10 @@ void mutt_expand_file_fmt (char *, size_t, const char *, const char *); void mutt_expand_fmt (char *, size_t, const char *, const char *); void mutt_expand_link (char *, const char *, const char *); void mutt_fetchPopMail (void); +void mutt_fix_reply_recipients (ENVELOPE *env); void mutt_folder_hook (char *); +void mutt_forward_intro (FILE *fp, HEADER *cur); +void mutt_forward_trailer (FILE *fp); void mutt_free_alias (ALIAS **); void mutt_free_body (BODY **); void mutt_free_color (int fg, int bg); @@ -153,7 +159,11 @@ void mutt_free_parameter (PARAMETER **); void mutt_generate_header (char *, size_t, HEADER *, int); void mutt_help (int); void mutt_linearize_tree (CONTEXT *, int); +void mutt_make_attribution (CONTEXT *ctx, HEADER *cur, FILE *out); +void mutt_make_forward_subject (ENVELOPE *env, CONTEXT *ctx, HEADER *cur); void mutt_make_help (char *, size_t, char *, int, int); +void mutt_make_misc_reply_headers (ENVELOPE *env, CONTEXT *ctx, HEADER *cur, ENVELOPE *curenv); +void mutt_make_post_indent (CONTEXT *ctx, HEADER *cur, FILE *out); void mutt_message (const char *, ...); void mutt_message_to_7bit (BODY *, FILE *); void mutt_mktemp (char *); @@ -212,12 +222,15 @@ int mutt_command_complete (char *, size_t, int, int); int mutt_var_value_complete (char *, size_t, int); int mutt_complete (char *, size_t); int mutt_compose_attachment (BODY *a); +int mutt_copy_body (FILE *, BODY **, BODY *); int mutt_decode_save_attachment (FILE *, BODY *, char *, int, int); int mutt_display_message (HEADER *h); int mutt_edit_attachment(BODY *); int mutt_edit_message (CONTEXT *, HEADER *); +int mutt_fetch_recips (ENVELOPE *out, ENVELOPE *in, int flags); int mutt_parent_message (CONTEXT *, HEADER *); -int mutt_prepare_template(CONTEXT *, HEADER *, HEADER *, short); +int mutt_prepare_template(FILE*, CONTEXT *, HEADER *, HEADER *, short); +int mutt_resend_message (FILE *, CONTEXT *, HEADER *); #define mutt_enter_fname(A,B,C,D,E) _mutt_enter_fname(A,B,C,D,E,0,NULL,NULL) int _mutt_enter_fname (const char *, char *, size_t, int *, int, int, char ***, int *); #define mutt_enter_string(A,B,C,D,E) _mutt_enter_string(A,B,C,D,E,0,NULL,NULL) @@ -264,7 +277,7 @@ int mutt_compose_menu (HEADER *, char *, size_t, HEADER *); int mutt_thread_set_flag (HEADER *, int, int, int); int mutt_user_is_recipient (HEADER *); void mutt_update_num_postponed (void); -int mutt_view_attachment (FILE*, BODY *, int); +int mutt_view_attachment (FILE*, BODY *, int, HEADER *, ATTACHPTR **, short); 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 *); @@ -414,6 +427,6 @@ int ioctl (int, int, ...); /* unsorted */ void ci_bounce_message (HEADER *, int *); -void ci_send_message (int, HEADER *, char *, CONTEXT *, HEADER *); +int ci_send_message (int, HEADER *, char *, CONTEXT *, HEADER *); diff --git a/recvattach.c b/recvattach.c index da82819d..3d72d643 100644 --- a/recvattach.c +++ b/recvattach.c @@ -519,17 +519,16 @@ mutt_query_pipe_attachment (char *command, FILE *fp, BODY *body, int filter) } } -static STATE state; -static void pipe_attachment (FILE *fp, BODY *b) +static void pipe_attachment (FILE *fp, BODY *b, STATE *state) { FILE *ifp; if (fp) { - state.fpin = fp; - mutt_decode_attachment (b, &state); + state->fpin = fp; + mutt_decode_attachment (b, state); if (AttachSep) - state_puts (AttachSep, &state); + state_puts (AttachSep, state); } else { @@ -538,27 +537,28 @@ static void pipe_attachment (FILE *fp, BODY *b) mutt_perror ("fopen"); return; } - mutt_copy_stream (ifp, state.fpout); + mutt_copy_stream (ifp, state->fpout); fclose (ifp); if (AttachSep) - state_puts (AttachSep, &state); + state_puts (AttachSep, state); } } static void -pipe_attachment_list (char *command, FILE *fp, int tag, BODY *top, int filter) +pipe_attachment_list (char *command, FILE *fp, int tag, BODY *top, int filter, + STATE *state) { for (; top; top = top->next) { if (!tag || top->tagged) { if (!filter && !option (OPTATTACHSPLIT)) - pipe_attachment (fp, top); + pipe_attachment (fp, top, state); else mutt_query_pipe_attachment (command, fp, top, filter); } else if (top->parts) - pipe_attachment_list (command, fp, tag, top->parts, filter); + pipe_attachment_list (command, fp, tag, top->parts, filter, state); if (!tag) break; } @@ -566,6 +566,7 @@ pipe_attachment_list (char *command, FILE *fp, int tag, BODY *top, int filter) void mutt_pipe_attachment_list (FILE *fp, int tag, BODY *top, int filter) { + STATE state; char buf[SHORT_STRING]; pid_t thepid; @@ -585,13 +586,13 @@ void mutt_pipe_attachment_list (FILE *fp, int tag, BODY *top, int filter) { endwin (); thepid = mutt_create_filter (buf, &state.fpout, NULL, NULL); - pipe_attachment_list (buf, fp, tag, top, filter); + pipe_attachment_list (buf, fp, tag, top, filter, &state); fclose (state.fpout); if (mutt_wait_filter (thepid) != 0 || option (OPTWAITKEY)) mutt_any_key_to_continue (NULL); } else - pipe_attachment_list (buf, fp, tag, top, filter); + pipe_attachment_list (buf, fp, tag, top, filter, &state); } static int can_print (BODY *top, int tag) @@ -624,7 +625,7 @@ static int can_print (BODY *top, int tag) return (1); } -static void print_attachment_list (FILE *fp, int tag, BODY *top) +static void print_attachment_list (FILE *fp, int tag, BODY *top, STATE *state) { char type [STRING]; @@ -638,7 +639,7 @@ static void print_attachment_list (FILE *fp, int tag, BODY *top) { if (!mutt_strcasecmp ("text/plain", top->subtype) || !mutt_strcasecmp ("application/postscript", top->subtype)) - pipe_attachment (fp, top); + pipe_attachment (fp, top, state); else if (mutt_can_decode (top)) { /* decode and print */ @@ -651,10 +652,10 @@ static void print_attachment_list (FILE *fp, int tag, BODY *top) { if ((ifp = fopen (newfile, "r")) != NULL) { - mutt_copy_stream (ifp, state.fpout); + mutt_copy_stream (ifp, state->fpout); fclose (ifp); if (AttachSep) - state_puts (AttachSep, &state); + state_puts (AttachSep, state); } } mutt_unlink (newfile); @@ -664,7 +665,7 @@ static void print_attachment_list (FILE *fp, int tag, BODY *top) mutt_print_attachment (fp, top); } else if (top->parts) - print_attachment_list (fp, tag, top->parts); + print_attachment_list (fp, tag, top->parts, state); if (!tag) return; } @@ -672,6 +673,8 @@ static void print_attachment_list (FILE *fp, int tag, BODY *top) void mutt_print_attachment_list (FILE *fp, int tag, BODY *top) { + STATE state; + pid_t thepid; if (query_quadoption (OPT_PRINT, tag ? _("Print tagged attachment(s)?") : _("Print attachment?")) != M_YES) return; @@ -683,255 +686,18 @@ void mutt_print_attachment_list (FILE *fp, int tag, BODY *top) endwin (); memset (&state, 0, sizeof (STATE)); thepid = mutt_create_filter (NONULL (PrintCmd), &state.fpout, NULL, NULL); - print_attachment_list (fp, tag, top); + print_attachment_list (fp, tag, top, &state); fclose (state.fpout); if (mutt_wait_filter (thepid) != 0 || option (OPTWAITKEY)) mutt_any_key_to_continue (NULL); } else - print_attachment_list (fp, tag, top); -} - -static void -bounce_attachment_list (ADDRESS *adr, int tag, BODY *body, HEADER *hdr) -{ - for (; body; body = body->next) - { - if (!tag || body->tagged) - { - if (!mutt_is_message_type (body->type, body->subtype)) - { - mutt_error _("You may only bounce message/rfc822 parts."); - continue; - } - body->hdr->msgno = hdr->msgno; - mutt_bounce_message (body->hdr, adr); - } - else if (body->parts) - bounce_attachment_list (adr, tag, body->parts, hdr); - if (!tag) - break; - } -} - -static void query_bounce_attachment (int tag, BODY *top, HEADER *hdr) -{ - char prompt[SHORT_STRING]; - char buf[HUGE_STRING]; - ADDRESS *adr = NULL; - int rc; - - buf[0] = 0; - - if(!tag) - strfcpy(prompt, _("Bounce message to: "), sizeof(prompt)); - else - strfcpy(prompt, _("Bounce tagged messages to: "), sizeof(prompt)); - - rc = mutt_get_field (prompt, buf, sizeof (buf), M_ALIAS); - - if (rc || !buf[0]) - return; - - adr = rfc822_parse_adrlist (adr, buf); - adr = mutt_expand_aliases (adr); - buf[0] = 0; - rfc822_write_address (buf, sizeof (buf), adr); - snprintf (prompt, sizeof (prompt), tag ? _("Bounce messages to %s...?") - : _("Bounce message to %s...?"), buf); - if (mutt_yesorno (prompt, 1) != 1) - { - rfc822_free_address (&adr); - CLEARLINE (LINES-1); - return; - } - bounce_attachment_list (adr, tag, top, hdr); - rfc822_free_address (&adr); -} - -static void -copy_tagged_attachments (FILE *fpout, FILE *fpin, const char *boundary, BODY *bdy) -{ - for (; bdy; bdy = bdy->next) - { - if (bdy->tagged) - { - fprintf (fpout, "\n--%s\n", boundary); - fseek (fpin, bdy->hdr_offset, 0); - mutt_copy_bytes (fpin, fpout, bdy->length + bdy->offset - bdy->hdr_offset); - } - else if (bdy->parts) - copy_tagged_attachments (fpout, fpin, boundary, bdy->parts); - } -} - -static int -create_tagged_message (const char *tempfile, - int tag, - CONTEXT *ctx, - HEADER *cur, - BODY *body) -{ - char *boundary; - MESSAGE *msg, *src; - CONTEXT tmpctx; - int magic; - - magic = DefaultMagic; - DefaultMagic = M_MBOX; - mx_open_mailbox (tempfile, M_APPEND, &tmpctx); - msg = mx_open_new_message (&tmpctx, cur, M_ADD_FROM); - src = mx_open_message (ctx, cur->msgno); - - if (tag) - { - mutt_copy_header (src->fp, cur, msg->fp, CH_XMIT, NULL); - boundary = mutt_get_parameter ("boundary", cur->content->parameter); - copy_tagged_attachments (msg->fp, src->fp, boundary, cur->content->parts); - fprintf (msg->fp, "--%s--\n", boundary); - } - else - { - /* single attachment */ - mutt_copy_header (src->fp, cur, msg->fp, CH_XMIT | CH_MIME | CH_NONEWLINE, NULL); - fputs ("Mime-Version: 1.0\n", msg->fp); - mutt_write_mime_header (body, msg->fp); - fputc ('\n', msg->fp); - fseek (src->fp, body->offset, 0); - mutt_copy_bytes (src->fp, msg->fp, body->length); - } - - mx_commit_message (msg, &tmpctx); - mx_close_message (&msg); - mx_close_message (&src); - mx_close_mailbox (&tmpctx); - DefaultMagic = magic; - return 0; -} - -/* op flag to ci_send_message() - * tag operate on tagged attachments? - * hdr current message - * body current attachment - */ - -/* - * XXX - this code looks way too complicated, and rather ineffective. - * Analyze and fix this. - */ - -/* - * Idea: - * - * 1. Forwarding - * - * Variant 1: mime_forward is set (or activated by the user). In this case, generate - * a new message whose main body contains the forwarded message's header, and - * attach all tagged attachments. - * - * Variant 2: mime_forward is not set (or activated). In this case, generate a new - * message whose main body contains the forwarded message's header, and formatted - * versions of all attachments we can handle in-line (i.e., hard-coded handlers + auto_view). - * - * When there are any tagged attachments we can't handle this way, ask the user - * whether he wants to ignore or whether he wants to attach them to the new message. - * Make this a quad-option. - * - * 2. Replying - * - * Always fall back to the behaviour from forwarding, variant 2. - * - * 3. Special handling for message/rfc822 attachments - * - * resend-message and bounce should be possible. forward and reply should have - * special semantics when they are applied ONLY to message/rfc822 body parts. - * - * Note: Some of this behaviour is implemented by the current code. However, DO NOT - * use it - it's horribly slow even on fast machines. We have sufficient information - * at hand to create the message structures needed by ci_send_message from scratch, and - * without any temporary folders. - * - * - * (Thanks to Roland Rosenfeld with whom I discussed this stuff.) - * - * tlr, Wed, 3 Nov 1999 21:29:19 +0100 - * - */ - -static void reply_attachment_list (int op, int tag, HEADER *hdr, BODY *body) -{ - HEADER *hn; - char tempfile[_POSIX_PATH_MAX]; - CONTEXT *ctx; - - if (!tag && body->hdr) - { - hn = body->hdr; - hn->msgno = hdr->msgno; /* required for MH/maildir */ - hn->replied = hdr->replied; - hn->read = hdr->read; - hn->old = hdr->old; - hn->changed = hdr->changed; - ctx = Context; - } - else - { - /* build a fake message which consists of only the tagged attachments */ - mutt_mktemp (tempfile); - create_tagged_message (tempfile, tag, Context, hdr, body); - ctx = mx_open_mailbox (tempfile, M_QUIET, NULL); - hn = ctx->hdrs[0]; - } - - if (op == SENDFORWARD && option (OPTFORWATTACH)) - { - HEADER *newhdr = mutt_new_header(); - char buffer [LONG_STRING]; - - mutt_message ("Preparing to forward..."); - if (mutt_prepare_template (ctx, newhdr, hn, 0) < 0) - { - mutt_clear_error(); - mutt_free_header (&newhdr); - goto cleanup; - } - - mutt_free_envelope (&newhdr->env); - newhdr->env = mutt_new_envelope(); - newhdr->received = 0; - newhdr->date_sent = 0; - - /* set the default subject for the message. */ - buffer[0] = 0; - mutt_make_string (buffer, sizeof (buffer), NONULL(ForwFmt), ctx, hn); - newhdr->env->subject = safe_strdup (buffer); - - mutt_clear_error(); - ci_send_message (0, newhdr, NULL, ctx, NULL); - } - else - ci_send_message (op, NULL, NULL, ctx, hn); - - if (hn->replied) - { - if (Context != ctx) - mutt_set_flag (Context, hdr, M_REPLIED, 1); - else - _mutt_set_flag (Context, hdr, M_REPLIED, 1, 0); - } - -cleanup: - - if (ctx != Context) - { - mx_fastclose_mailbox (ctx); - safe_free ((void **) &ctx); - unlink (tempfile); - } + print_attachment_list (fp, tag, top, &state); } void -mutt_attach_display_loop (MUTTMENU *menu, int op, FILE *fp, ATTACHPTR **idx) +mutt_attach_display_loop (MUTTMENU *menu, int op, FILE *fp, HEADER *hdr, + ATTACHPTR **idx, short idxlen) { #if 0 int old_optweed = option (OPTWEED); @@ -947,7 +713,8 @@ mutt_attach_display_loop (MUTTMENU *menu, int op, FILE *fp, ATTACHPTR **idx) /* fall through */ case OP_VIEW_ATTACH: - op = mutt_view_attachment (fp, idx[menu->current]->content, M_REGULAR); + op = mutt_view_attachment (fp, idx[menu->current]->content, M_REGULAR, + hdr, idx, idxlen); break; case OP_NEXT_ENTRY: @@ -1062,17 +829,19 @@ void mutt_view_attachments (HEADER *hdr) { case OP_DISPLAY_HEADERS: case OP_VIEW_ATTACH: - mutt_attach_display_loop (menu, op, fp, idx); + mutt_attach_display_loop (menu, op, fp, hdr, idx, idxlen); menu->redraw = REDRAW_FULL; break; case OP_ATTACH_VIEW_MAILCAP: - mutt_view_attachment (fp, idx[menu->current]->content, M_MAILCAP); + mutt_view_attachment (fp, idx[menu->current]->content, M_MAILCAP, + hdr, idx, idxlen); menu->redraw = REDRAW_FULL; break; case OP_ATTACH_VIEW_TEXT: - mutt_view_attachment (fp, idx[menu->current]->content, M_AS_TEXT); + mutt_view_attachment (fp, idx[menu->current]->content, M_AS_TEXT, + hdr, idx, idxlen); menu->redraw = REDRAW_FULL; break; @@ -1080,7 +849,8 @@ void mutt_view_attachments (HEADER *hdr) #ifdef _PGPPATH case OP_EXTRACT_KEYS: - pgp_extract_keys_from_attachment_list (fp, menu->tagprefix, menu->tagprefix ? cur : idx[menu->current]->content); + pgp_extract_keys_from_attachment_list (fp, menu->tagprefix, + menu->tagprefix ? cur : idx[menu->current]->content); menu->redraw = REDRAW_FULL; break; #endif @@ -1088,16 +858,20 @@ void mutt_view_attachments (HEADER *hdr) case OP_PRINT: - mutt_print_attachment_list (fp, menu->tagprefix, menu->tagprefix ? cur : idx[menu->current]->content); + mutt_print_attachment_list (fp, menu->tagprefix, + menu->tagprefix ? cur : idx[menu->current]->content); break; case OP_PIPE: - mutt_pipe_attachment_list (fp, menu->tagprefix, menu->tagprefix ? cur : idx[menu->current]->content, 0); + mutt_pipe_attachment_list (fp, menu->tagprefix, + menu->tagprefix ? cur : idx[menu->current]->content, 0); break; case OP_SAVE: - mutt_save_attachment_list (fp, menu->tagprefix, menu->tagprefix ? cur : idx[menu->current]->content, hdr); - if (option (OPTRESOLVE) && menu->current < menu->max - 1) + mutt_save_attachment_list (fp, menu->tagprefix, + menu->tagprefix ? cur : idx[menu->current]->content, hdr); + + if (option (OPTRESOLVE) && menu->current < menu->max - 1) menu->current++; menu->redraw = REDRAW_MOTION_RESYNCH | REDRAW_FULL; @@ -1184,39 +958,38 @@ void mutt_view_attachments (HEADER *hdr) } break; + case OP_RESEND: + CHECK_ATTACH; + mutt_attach_resend (fp, hdr, idx, idxlen, + menu->tagprefix ? NULL : idx[menu->current]->content); + menu->redraw = REDRAW_FULL; + break; + case OP_BOUNCE_MESSAGE: CHECK_ATTACH; - query_bounce_attachment (menu->tagprefix, menu->tagprefix ? cur : idx[menu->current]->content, hdr); - break; + mutt_attach_bounce (fp, hdr, idx, idxlen, + menu->tagprefix ? NULL : idx[menu->current]->content); + menu->redraw = REDRAW_FULL; + break; + case OP_FORWARD_MESSAGE: + CHECK_ATTACH; + mutt_attach_forward (fp, hdr, idx, idxlen, + menu->tagprefix ? NULL : idx[menu->current]->content); + menu->redraw = REDRAW_FULL; + break; + case OP_REPLY: case OP_GROUP_REPLY: case OP_LIST_REPLY: - case OP_FORWARD_MESSAGE: CHECK_ATTACH; - -#ifdef _PGPPATH - if ((hdr->pgp & PGPENCRYPT) && hdr->content->type == TYPEMULTIPART) - { - mutt_error _( - "This operation is not currently supported for PGP messages."); - break; - } -#endif - - - - if (op == OP_FORWARD_MESSAGE) - flags = SENDFORWARD; - else - flags = SENDREPLY | - (op == OP_GROUP_REPLY ? SENDGROUPREPLY : 0) | - (op == OP_LIST_REPLY ? SENDLISTREPLY : 0); - reply_attachment_list (flags, - menu->tagprefix, - hdr, - menu->tagprefix ? cur : idx[menu->current]->content); + + flags = SENDREPLY | + (op == OP_GROUP_REPLY ? SENDGROUPREPLY : 0) | + (op == OP_LIST_REPLY ? SENDLISTREPLY : 0); + mutt_attach_reply (fp, hdr, idx, idxlen, + menu->tagprefix ? NULL : idx[menu->current]->content, flags); menu->redraw = REDRAW_FULL; break; diff --git a/recvcmd.c b/recvcmd.c new file mode 100644 index 00000000..8dff3ba4 --- /dev/null +++ b/recvcmd.c @@ -0,0 +1,873 @@ +/* + * Copyright (C) 1999 Thomas Roessler + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA + * 02139, USA. + */ + +#include "mutt.h" +#include "mutt_curses.h" +#include "mutt_menu.h" +#include "rfc1524.h" +#include "mime.h" +#include "mailbox.h" +#include "attach.h" +#include "mapping.h" +#include "mx.h" +#include "copy.h" + + +/* some helper functions to verify that we are exclusively operating + * on message/rfc822 attachments + */ + +static short check_msg (BODY * b, short err) +{ + if (!mutt_is_message_type (b->type, b->subtype)) + { + if (err) + mutt_error _("You may only bounce message/rfc822 parts."); + return -1; + } + return 0; +} + +static short check_all_msg (ATTACHPTR ** idx, short idxlen, + BODY * cur, short err) +{ + short i; + + if (cur && check_msg (cur, err) == -1) + return -1; + else if (!cur) + { + for (i = 0; i < idxlen; i++) + { + if (idx[i]->content->tagged) + { + if (check_msg (idx[i]->content, err) == -1) + return -1; + } + } + } + return 0; +} + + +/* can we decode all tagged attachments? */ + +static short check_can_decode (ATTACHPTR ** idx, short idxlen, + BODY * cur) +{ + short i; + + if (cur) + return mutt_can_decode (cur); + + for (i = 0; i < idxlen; i++) + if (idx[i]->content->tagged && !mutt_can_decode (idx[i]->content)) + return 0; + + return 1; +} + +static short count_tagged (ATTACHPTR **idx, short idxlen) +{ + short count = 0; + short i; + + for (i = 0; i < idxlen; i++) + if (idx[i]->content->tagged) + count++; + + return count; +} + +/* count the number of tagged children below a multipart or message + * attachment. + */ + +static short count_tagged_children (ATTACHPTR ** idx, + short idxlen, short i) +{ + short level = idx[i]->level; + short count = 0; + + while ((++i < idxlen) && (level < idx[i]->level)) + if (idx[i]->content->tagged) + count++; + + return count; +} + + + +/** + ** + ** The bounce function, from the attachment menu + ** + **/ + +void mutt_attach_bounce (FILE * fp, HEADER * hdr, + ATTACHPTR ** idx, short idxlen, BODY * cur) +{ + short i; + short ntagged; + char prompt[STRING]; + char buf[HUGE_STRING]; + ADDRESS *adr = NULL; + + if (check_all_msg (idx, idxlen, cur, 1) == -1) + return; + + ntagged = count_tagged (idx, idxlen); + + if (cur || ntagged == 1) + strfcpy (prompt, _("Bounce message to: "), sizeof (prompt)); + else + strfcpy (prompt, _("Bounce tagged messages to: "), sizeof (prompt)); + + buf[0] = '\0'; + if (mutt_get_field (prompt, buf, sizeof (buf), M_ALIAS) + || buf[0] == '\0') + return; + + adr = rfc822_parse_adrlist (adr, buf); + adr = mutt_expand_aliases (adr); + buf[0] = 0; + rfc822_write_address (buf, sizeof (buf), adr); + + snprintf (prompt, sizeof (prompt), + cur ? _("Bounce message to %s...?") : _("Bounce messages to %s...?"), buf); + + if (mutt_yesorno (prompt, 1) != 1) + goto bail; + + if (cur) + mutt_bounce_message (fp, cur->hdr, adr); + else + { + for (i = 0; i < idxlen; i++) + { + if (idx[i]->content->tagged) + mutt_bounce_message (fp, idx[i]->content->hdr, adr); + } + } + +bail: + + rfc822_free_address (&adr); + CLEARLINE (LINES - 1); +} + + + +/** + ** + ** resend-message, from the attachment menu + ** + ** + **/ + +void mutt_attach_resend (FILE * fp, HEADER * hdr, ATTACHPTR ** idx, + short idxlen, BODY * cur) +{ + short i; + + if (check_all_msg (idx, idxlen, cur, 1) == -1) + return; + + if (cur) + mutt_resend_message (fp, Context, cur->hdr); + else + { + for (i = 0; i < idxlen; i++) + if (idx[i]->content->tagged) + mutt_resend_message (fp, Context, idx[i]->content->hdr); + } +} + + +/** + ** + ** forward-message, from the attachment menu + ** + **/ + +/* try to find a common parent message for the tagged attachments. */ + +static HEADER *find_common_parent (ATTACHPTR ** idx, short idxlen, + short nattach) +{ + short i; + short nchildren; + + for (i = 0; i < idxlen; i++) + if (idx[i]->content->tagged) + break; + + while (--i >= 0) + { + if (mutt_is_message_type (idx[i]->content->type, idx[i]->content->subtype)) + { + nchildren = count_tagged_children (idx, idxlen, i); + if (nchildren == nattach) + return idx[i]->content->hdr; + } + } + + return NULL; +} + +/* + * check whether attachment #i is a parent of the attachment + * pointed to by cur + * + * Note: This and the calling procedure could be optimized quite a + * bit. For now, it's not worth the effort. + */ + +static int is_parent (short i, ATTACHPTR **idx, short idxlen, BODY *cur) +{ + short level = idx[i]->level; + + while ((++i < idxlen) && idx[i]->level > level) + { + if (idx[i]->content == cur) + return 1; + } + + return 0; +} + +static HEADER *find_parent (ATTACHPTR **idx, short idxlen, BODY *cur, short nattach) +{ + short i; + HEADER *parent = NULL; + + if (cur) + { + for (i = 0; i < idxlen; i++) + { + if (mutt_is_message_type (idx[i]->content->type, idx[i]->content->subtype) + && is_parent (i, idx, idxlen, cur)) + parent = idx[i]->content->hdr; + if (idx[i]->content == cur) + break; + } + } + else if (nattach) + parent = find_common_parent (idx, idxlen, nattach); + + return parent; +} + +static void include_header (int quote, FILE * ifp, + HEADER * hdr, FILE * ofp, + char *_prefix) +{ + int chflags = CH_DECODE; + char prefix[SHORT_STRING]; + + if (option (OPTWEED)) + chflags |= CH_WEED | CH_REORDER; + + if (quote) + { + if (_prefix) + strfcpy (prefix, _prefix, sizeof (prefix)); + else + _mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix), + Context, hdr, 0); + + chflags |= CH_PREFIX; + } + + mutt_copy_header (ifp, hdr, ofp, chflags, quote ? prefix : NULL); +} + +/* Attach all the body parts which can't be decoded. + * This code is shared by forwarding and replying. */ + +static BODY ** copy_problematic_attachments (FILE *fp, + BODY **last, + ATTACHPTR **idx, + short idxlen, + short force) +{ + short i; + + for (i = 0; i < idxlen; i++) + { + if (idx[i]->content->tagged && + (force || !mutt_can_decode (idx[i]->content))) + { + if (mutt_copy_body (fp, last, idx[i]->content) == -1) + return NULL; /* XXXXX - may lead to crashes */ + last = &((*last)->next); + } + } + return last; +} + +/* + * forward one or several MIME bodies + * (non-message types) + */ + +static void attach_forward_bodies (FILE * fp, HEADER * hdr, + ATTACHPTR ** idx, short idxlen, + BODY * cur, + short nattach) +{ + short i; + short mime_fwd_all = 0; + short mime_fwd_any = 1; + HEADER *parent = NULL; + HEADER *tmphdr = NULL; + BODY **last; + char tmpbody[_POSIX_PATH_MAX]; + FILE *tmpfp = NULL; + + char prefix[STRING]; + + int rc = 0; + + STATE st; + + /* + * First, find the parent message. + * Note: This could be made an option by just + * putting the following lines into an if block. + */ + + + parent = find_parent (idx, idxlen, cur, nattach); + + if (parent == NULL) + parent = hdr; + + + tmphdr = mutt_new_header (); + tmphdr->env = mutt_new_envelope (); + mutt_make_forward_subject (tmphdr->env, Context, parent); + + mutt_mktemp (tmpbody); + if ((tmpfp = safe_fopen (tmpbody, "w")) == NULL) + { + mutt_error (_("Can't open temporary file %s."), tmpbody); + return; + } + + mutt_forward_intro (tmpfp, parent); + + /* prepare the prefix here since we'll need it later. */ + + if (option (OPTFORWQUOTE)) + _mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix), Context, + parent, 0); + + include_header (option (OPTFORWQUOTE), fp, parent, + tmpfp, prefix); + + + /* + * Now, we have prepared the first part of the message body: The + * original message's header. + * + * The next part is more interesting: either include the message bodies, + * or attach them. + */ + + if ((!cur || mutt_can_decode (cur)) && + (rc = query_quadoption (OPT_MIMEFWD, + _("Forward MIME encapsulated?"))) == M_YES) + mime_fwd_all = 1; + else if (rc == -1) + goto bail; + + /* + * shortcut MIMEFWDREST when there is only one attachment. Is + * this intuitive? + */ + + if (!mime_fwd_all && !cur && (nattach > 1) + && !check_can_decode (idx, idxlen, cur)) + { + if ((rc = query_quadoption (OPT_MIMEFWDREST, +_("Can't decode all tagged attachments. MIME-forward the others?"))) == -1) + goto bail; + else if (rc == M_NO) + mime_fwd_any = 0; + } + + /* initialize a state structure */ + + memset (&st, 0, sizeof (st)); + + if (option (OPTFORWQUOTE)) + st.prefix = prefix; + st.flags = M_CHARCONV; + if (option (OPTWEED)) + st.flags |= M_WEED; + st.fpin = fp; + st.fpout = tmpfp; + + /* where do we append new MIME parts? */ + last = &tmphdr->content; + + if (cur) + { + /* single body case */ + + if (!mime_fwd_all && mutt_can_decode (cur)) + { + mutt_body_handler (cur, &st); + state_putc ('\n', &st); + } + else + { + if (mutt_copy_body (fp, last, cur) == -1) + goto bail; + last = &((*last)->next); + } + } + else + { + /* multiple body case */ + + if (!mime_fwd_all) + { + for (i = 0; i < idxlen; i++) + { + if (idx[i]->content->tagged && mutt_can_decode (idx[i]->content)) + { + mutt_body_handler (idx[i]->content, &st); + state_putc ('\n', &st); + } + } + } + + if (mime_fwd_any && + (last = copy_problematic_attachments (fp, last, idx, idxlen, mime_fwd_all)) == NULL) + goto bail; + } + + mutt_forward_trailer (tmpfp); + + fclose (tmpfp); + tmpfp = NULL; + + /* now that we have the template, send it. */ + ci_send_message (0, tmphdr, tmpbody, NULL, parent); + return; + + bail: + + if (tmpfp) + { + fclose (tmpfp); + mutt_unlink (tmpbody); + } + + mutt_free_header (&tmphdr); +} + + +/* + * Forward one or several message-type attachments. This + * is different from the previous function + * since we want to mimic the index menu's behaviour. + * + * Code reuse from ci_send_message is not possible here - + * ci_send_message relies on a context structure to find messages, + * while, on the attachment menu, messages are referenced through + * the attachment index. + */ + +static void attach_forward_msgs (FILE * fp, HEADER * hdr, + ATTACHPTR ** idx, short idxlen, BODY * cur) +{ + HEADER *curhdr = NULL; + HEADER *tmphdr; + short i; + int rc; + + BODY **last; + char tmpbody[_POSIX_PATH_MAX]; + FILE *tmpfp = NULL; + + int cmflags = 0; + int chflags = CH_XMIT; + + if (cur) + curhdr = cur->hdr; + else + { + for (i = 0; i < idxlen; i++) + if (idx[i]->content->tagged) + { + curhdr = idx[i]->content->hdr; + break; + } + } + + tmphdr = mutt_new_header (); + tmphdr->env = mutt_new_envelope (); + mutt_make_forward_subject (tmphdr->env, Context, curhdr); + + + tmpbody[0] = '\0'; + + if ((rc = query_quadoption (OPT_MIMEFWD, + _("Forward MIME encapsulated?"))) == M_NO) + { + + /* no MIME encapsulation */ + + mutt_mktemp (tmpbody); + if (!(tmpfp = safe_fopen (tmpbody, "w"))) + { + mutt_error (_("Can't create %s."), tmpbody); + mutt_free_header (&tmphdr); + return; + } + + if (option (OPTFORWQUOTE)) + { + chflags |= CH_PREFIX; + cmflags |= M_CM_PREFIX; + } + + if (option (OPTFORWDECODE)) + { + cmflags |= M_CM_DECODE | M_CM_CHARCONV; + if (option (OPTWEED)) + { + chflags |= CH_WEED | CH_REORDER; + cmflags |= M_CM_WEED; + } + } + + + if (cur) + { + mutt_forward_intro (tmpfp, cur->hdr); + _mutt_copy_message (tmpfp, fp, cur->hdr, cur->hdr->content, cmflags, chflags); + mutt_forward_trailer (tmpfp); + } + else + { + for (i = 0; i < idxlen; i++) + { + if (idx[i]->content->tagged) + { + mutt_forward_intro (tmpfp, idx[i]->content->hdr); + _mutt_copy_message (tmpfp, fp, idx[i]->content->hdr, + idx[i]->content->hdr->content, cmflags, chflags); + mutt_forward_trailer (tmpfp); + } + } + } + fclose (tmpfp); + } + else if (rc == M_YES) /* do MIME encapsulation - we don't need to do much here */ + { + last = &tmphdr->content; + if (cur) + mutt_copy_body (fp, last, cur); + else + { + for (i = 0; i < idxlen; i++) + if (idx[i]->content->tagged) + { + mutt_copy_body (fp, last, idx[i]->content); + last = &((*last)->next); + } + } + } + else + mutt_free_header (&tmphdr); + + ci_send_message (0, tmphdr, *tmpbody ? tmpbody : NULL, + NULL, curhdr); + +} + +void mutt_attach_forward (FILE * fp, HEADER * hdr, + ATTACHPTR ** idx, short idxlen, BODY * cur) +{ + short nattach; + + + if (check_all_msg (idx, idxlen, cur, 0) == 0) + attach_forward_msgs (fp, hdr, idx, idxlen, cur); + else + { + nattach = count_tagged (idx, idxlen); + attach_forward_bodies (fp, hdr, idx, idxlen, cur, nattach); + } +} + + + +/** + ** + ** the various reply functions, from the attachment menu + ** + ** + **/ + +/* Create the envelope defaults for a reply. + * + * This function can be invoked in two ways. + * + * Either, parent is NULL. In this case, all tagged bodies are of a message type, + * and the header information is fetched from them. + * + * Or, parent is non-NULL. In this case, cur is the common parent of all the + * tagged attachments. + * + * Note that this code is horribly similar to envelope_defaults () from send.c. + */ + +static int +attach_reply_envelope_defaults (ENVELOPE *env, ATTACHPTR **idx, short idxlen, + HEADER *parent, int flags) +{ + ENVELOPE *curenv = NULL; + HEADER *curhdr = NULL; + short i; + + if (!parent) + { + for (i = 0; i < idxlen; i++) + { + if (idx[i]->content->tagged) + { + curhdr = idx[i]->content->hdr; + curenv = curhdr->env; + break; + } + } + } + else + { + curenv = parent->env; + curhdr = parent; + } + + if (curenv == NULL || curhdr == NULL) + { + mutt_error _("Can't find any tagged messages."); + return -1; + } + + if (parent) + { + if (mutt_fetch_recips (env, curenv, flags) == -1) + return -1; + } + else + { + for (i = 0; i < idxlen; i++) + { + if (idx[i]->content->tagged + && mutt_fetch_recips (env, idx[i]->content->hdr->env, flags) == -1) + return -1; + } + } + + if ((flags & SENDLISTREPLY) && !env->to) + { + mutt_error _("No mailing lists found!"); + return (-1); + } + + mutt_fix_reply_recipients (env); + mutt_make_misc_reply_headers (env, Context, curhdr, curenv); + + if (parent) + env->references = mutt_make_references (curenv); + else + { + LIST **p; + + env->references = NULL; + p = &env->references; + + for (i = 0; i < idxlen; i++) + { + if (idx[i]->content->tagged) + { + while (*p) p = &(*p)->next; + *p = mutt_make_references (idx[i]->content->hdr->env); + } + } + } + + return 0; +} + + +/* This is _very_ similar to send.c's include_reply(). */ + +static void attach_include_reply (FILE *fp, FILE *tmpfp, HEADER *cur, int flags) +{ + int cmflags = M_CM_PREFIX | M_CM_DECODE | M_CM_CHARCONV; + int chflags = CH_DECODE; + + mutt_make_attribution (Context, cur, tmpfp); + + if (!option (OPTHEADER)) + cmflags |= M_CM_NOHEADER; + if (option (OPTWEED)) + { + chflags |= CH_WEED; + cmflags |= M_CM_WEED; + } + + _mutt_copy_message (tmpfp, fp, cur, cur->content, cmflags, chflags); + mutt_make_post_indent (Context, cur, tmpfp); +} + +void mutt_attach_reply (FILE * fp, HEADER * hdr, + ATTACHPTR ** idx, short idxlen, BODY * cur, + int flags) +{ + short mime_reply_any = 0; + + short nattach = 0; + HEADER *parent = NULL; + HEADER *tmphdr = NULL; + short i; + + STATE st; + char tmpbody[_POSIX_PATH_MAX]; + FILE *tmpfp; + + char prefix[SHORT_STRING]; + int rc; + + if (check_all_msg (idx, idxlen, cur, 0) == -1) + { + nattach = count_tagged (idx, idxlen); + if ((parent = find_parent (idx, idxlen, cur, nattach)) == NULL) + parent = hdr; + } + + if (nattach > 1 && !check_can_decode (idx, idxlen, cur)) + { + if ((rc = query_quadoption (OPT_MIMEFWDREST, + _("Can't decode all tagged attachments. MIME-encapsulate the others?"))) == -1) + return; + else if (rc == M_YES) + mime_reply_any = 1; + } + else if (nattach == 1) + mime_reply_any = 1; + + tmphdr = mutt_new_header (); + tmphdr->env = mutt_new_envelope (); + + if (attach_reply_envelope_defaults (tmphdr->env, idx, idxlen, + parent ? parent : cur->hdr, flags) == -1) + { + mutt_free_header (&tmphdr); + return; + } + + mutt_mktemp (tmpbody); + if ((tmpfp = safe_fopen (tmpbody, "w")) == NULL) + { + mutt_error (_("Can't create %s."), tmpbody); + mutt_free_header (&tmphdr); + return; + } + + if (!parent) + { + if (cur) + attach_include_reply (fp, tmpfp, cur->hdr, flags); + else + { + for (i = 0; i < idxlen; i++) + { + if (idx[i]->content->tagged) + attach_include_reply (fp, tmpfp, idx[i]->content->hdr, flags); + } + } + } + else + { + mutt_make_attribution (Context, parent, tmpfp); + + memset (&st, 0, sizeof (STATE)); + st.fpin = fp; + st.fpout = tmpfp; + + _mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix), + Context, parent, 0); + + st.prefix = prefix; + st.flags = M_CHARCONV; + + if (option (OPTWEED)) + st.flags |= M_WEED; + + if (option (OPTHEADER)) + include_header (1, fp, parent, tmpfp, prefix); + + if (cur) + { + if (mutt_can_decode (cur)) + { + mutt_body_handler (cur, &st); + state_putc ('\n', &st); + } + else + mutt_copy_body (fp, &tmphdr->content, cur); + } + else + { + for (i = 0; i < idxlen; i++) + { + if (idx[i]->content->tagged && mutt_can_decode (idx[i]->content)) + { + mutt_body_handler (idx[i]->content, &st); + state_putc ('\n', &st); + } + } + } + + mutt_make_post_indent (Context, parent, tmpfp); + + if (mime_reply_any && !cur && + copy_problematic_attachments (fp, &tmphdr->content, idx, idxlen, 0) == NULL) + { + mutt_free_header (&tmphdr); + fclose (tmpfp); + return; + } + } + + fclose (tmpfp); + + if (ci_send_message (flags, tmphdr, tmpbody, NULL, parent) == 0) + mutt_set_flag (Context, hdr, M_REPLIED, 1); +} + diff --git a/rfc1524.c b/rfc1524.c index 6f803dbc..39181880 100644 --- a/rfc1524.c +++ b/rfc1524.c @@ -420,45 +420,6 @@ int rfc1524_mailcap_lookup (BODY *a, char *type, rfc1524_entry *entry, int opt) return found; } -/* Modified by blong to accept a "suggestion" for file name. If - * that file exists, then construct one with unique name but - * keep any extension. This might fail, I guess. - * Renamed to mutt_adv_mktemp so I only have to change where it's - * called, and not all possible cases. - */ -void mutt_adv_mktemp (char *s, size_t l) -{ - char buf[_POSIX_PATH_MAX]; - char tmp[_POSIX_PATH_MAX]; - char *period; - size_t sl; - struct stat sb; - - strfcpy (buf, NONULL (Tempdir), sizeof (buf)); - mutt_expand_path (buf, sizeof (buf)); - if (s[0] == '\0') - { - snprintf (s, l, "%s/muttXXXXXX", buf); - mktemp (s); - } - else - { - strfcpy (tmp, s, sizeof (tmp)); - snprintf (s, l, "%s/%s", buf, tmp); - if (lstat (s, &sb) == -1 && errno == ENOENT) - return; - if ((period = strrchr (tmp, '.')) != NULL) - *period = 0; - snprintf (s, l, "%s/%s.XXXXXX", buf, tmp); - mktemp (s); - if (period != NULL) - { - *period = '.'; - sl = mutt_strlen(s); - strfcpy(s + sl, period, l - sl); - } - } -} /* This routine will create a _temporary_ filename matching the * name template given if this needs to be done. diff --git a/rfc1524.h b/rfc1524.h index 1051f111..38f5bc49 100644 --- a/rfc1524.h +++ b/rfc1524.h @@ -39,7 +39,6 @@ void rfc1524_free_entry (rfc1524_entry **); int rfc1524_expand_command (BODY *, char *, char *, char *, int); int rfc1524_expand_filename (char *, char *, char *, size_t); int rfc1524_mailcap_lookup (BODY *, char *, rfc1524_entry *, int); -void mutt_adv_mktemp (char *, size_t); int mutt_rename_file (char *, char *); #endif /* _RFC1524_H */ diff --git a/send.c b/send.c index afa4c74d..4d880cc1 100644 --- a/send.c +++ b/send.c @@ -314,9 +314,25 @@ LIST *mutt_copy_list (LIST *p) return (l); } -static int include_forward (CONTEXT *ctx, HEADER *cur, FILE *out) +void mutt_forward_intro (FILE *fp, HEADER *cur) { char buffer[STRING]; + + fputs ("----- Forwarded message from ", fp); + buffer[0] = 0; + rfc822_write_address (buffer, sizeof (buffer), cur->env->from); + fputs (buffer, fp); + fputs (" -----\n\n", fp); +} + +void mutt_forward_trailer (FILE *fp) +{ + fputs ("\n----- End forwarded message -----\n", fp); +} + + +static int include_forward (CONTEXT *ctx, HEADER *cur, FILE *out) +{ int chflags = CH_DECODE, cmflags = 0; @@ -328,13 +344,8 @@ static int include_forward (CONTEXT *ctx, HEADER *cur, FILE *out) } #endif /* _PGPPATH */ + mutt_forward_intro (out, cur); - - fputs ("----- Forwarded message from ", out); - buffer[0] = 0; - rfc822_write_address (buffer, sizeof (buffer), cur->env->from); - fputs (buffer, out); - fputs (" -----\n\n", out); if (option (OPTFORWDECODE)) { cmflags |= M_CM_DECODE | M_CM_CHARCONV; @@ -348,13 +359,34 @@ static int include_forward (CONTEXT *ctx, HEADER *cur, FILE *out) cmflags |= M_CM_PREFIX; mutt_parse_mime_message (ctx, cur); mutt_copy_message (out, ctx, cur, cmflags, chflags); - fputs ("\n----- End forwarded message -----\n", out); + mutt_forward_trailer (out); return 0; } -static int include_reply (CONTEXT *ctx, HEADER *cur, FILE *out) +void mutt_make_attribution (CONTEXT *ctx, HEADER *cur, FILE *out) +{ + char buffer[STRING]; + if (Attribution) + { + mutt_make_string (buffer, sizeof (buffer), Attribution, ctx, cur); + fputs (buffer, out); + fputc ('\n', out); + } +} + +void mutt_make_post_indent (CONTEXT *ctx, HEADER *cur, FILE *out) { char buffer[STRING]; + if (PostIndentString) + { + mutt_make_string (buffer, sizeof (buffer), PostIndentString, ctx, cur); + fputs (buffer, out); + fputc ('\n', out); + } +} + +static int include_reply (CONTEXT *ctx, HEADER *cur, FILE *out) +{ int cmflags = M_CM_PREFIX | M_CM_DECODE | M_CM_CHARCONV; int chflags = CH_DECODE; @@ -369,12 +401,8 @@ static int include_reply (CONTEXT *ctx, HEADER *cur, FILE *out) } #endif /* _PGPPATH */ - if (Attribution) - { - mutt_make_string (buffer, sizeof (buffer), Attribution, ctx, cur); - fputs (buffer, out); - fputc ('\n', out); - } + mutt_make_attribution (ctx, cur, out); + if (!option (OPTHEADER)) cmflags |= M_CM_NOHEADER; if (option (OPTWEED)) @@ -385,12 +413,9 @@ static int include_reply (CONTEXT *ctx, HEADER *cur, FILE *out) mutt_parse_mime_message (ctx, cur); mutt_copy_message (out, ctx, cur, cmflags, chflags); - if (PostIndentString) - { - mutt_make_string (buffer, sizeof (buffer), PostIndentString, ctx, cur); - fputs (buffer, out); - fputc ('\n', out); - } + + mutt_make_post_indent (ctx, cur, out); + return 0; } @@ -463,7 +488,7 @@ static int default_to (ADDRESS **to, ENVELOPE *env, int group) return (0); } -static int fetch_recips (ENVELOPE *out, ENVELOPE *in, int flags) +int mutt_fetch_recips (ENVELOPE *out, ENVELOPE *in, int flags) { ADDRESS *tmp; if (flags & SENDLISTREPLY) @@ -487,7 +512,7 @@ static int fetch_recips (ENVELOPE *out, ENVELOPE *in, int flags) return 0; } -static LIST *make_references(ENVELOPE *e) +LIST *mutt_make_references(ENVELOPE *e) { LIST *t, *l; @@ -504,12 +529,69 @@ static LIST *make_references(ENVELOPE *e) return l; } +void mutt_fix_reply_recipients (ENVELOPE *env) +{ + if (! option (OPTMETOO)) + { + /* the order is important here. do the CC: first so that if the + * the user is the only recipient, it ends up on the TO: field + */ + env->cc = remove_user (env->cc, (env->to == NULL)); + env->to = remove_user (env->to, (env->cc == NULL)); + } + + /* the CC field can get cluttered, especially with lists */ + env->to = mutt_remove_duplicates (env->to); + env->cc = mutt_remove_duplicates (env->cc); + env->cc = mutt_remove_xrefs (env->to, env->cc); +} + +void mutt_make_forward_subject (ENVELOPE *env, CONTEXT *ctx, HEADER *cur) +{ + char buffer[STRING]; + + /* set the default subject for the message. */ + mutt_make_string (buffer, sizeof (buffer), NONULL(ForwFmt), ctx, cur); + env->subject = safe_strdup (buffer); +} + +void mutt_make_misc_reply_headers (ENVELOPE *env, CONTEXT *ctx, + HEADER *cur, ENVELOPE *curenv) +{ + LIST *tmp; + char buffer[STRING]; + + if (curenv->real_subj) + { + env->subject = safe_malloc (mutt_strlen (curenv->real_subj) + 5); + sprintf (env->subject, "Re: %s", curenv->real_subj); + } + else + env->subject = safe_strdup ("Re: your mail"); + + /* add the In-Reply-To field */ + if (InReplyTo) + { + strfcpy (buffer, "In-Reply-To: ", sizeof (buffer)); + mutt_make_string (buffer + 13, sizeof (buffer) - 13, InReplyTo, ctx, cur); + tmp = env->userhdrs; + while (tmp && tmp->next) + tmp = tmp->next; + if (tmp) + { + tmp->next = mutt_new_list (); + tmp = tmp->next; + } + else + tmp = env->userhdrs = mutt_new_list (); + tmp->data = safe_strdup (buffer); + } +} + static int envelope_defaults (ENVELOPE *env, CONTEXT *ctx, HEADER *cur, int flags) { ENVELOPE *curenv = NULL; - LIST *tmp; - char buffer[STRING]; int i = 0, tag = 0; if (!cur) @@ -544,11 +626,11 @@ envelope_defaults (ENVELOPE *env, CONTEXT *ctx, HEADER *cur, int flags) for (i = 0; i < ctx->vcount; i++) { h = ctx->hdrs[ctx->v2r[i]]; - if (h->tagged && fetch_recips (env, h->env, flags) == -1) + if (h->tagged && mutt_fetch_recips (env, h->env, flags) == -1) return -1; } } - else if (fetch_recips (env, curenv, flags) == -1) + else if (mutt_fetch_recips (env, curenv, flags) == -1) return -1; if ((flags & SENDLISTREPLY) && !env->to) @@ -557,46 +639,9 @@ envelope_defaults (ENVELOPE *env, CONTEXT *ctx, HEADER *cur, int flags) return (-1); } - if (! option (OPTMETOO)) - { - /* the order is important here. do the CC: first so that if the - * the user is the only recipient, it ends up on the TO: field - */ - env->cc = remove_user (env->cc, (env->to == NULL)); - env->to = remove_user (env->to, (env->cc == NULL)); - } - - /* the CC field can get cluttered, especially with lists */ - env->to = mutt_remove_duplicates (env->to); - env->cc = mutt_remove_duplicates (env->cc); - env->cc = mutt_remove_xrefs (env->to, env->cc); - - if (curenv->real_subj) - { - env->subject = safe_malloc (mutt_strlen (curenv->real_subj) + 5); - sprintf (env->subject, "Re: %s", curenv->real_subj); - } - else - env->subject = safe_strdup ("Re: your mail"); - - /* add the In-Reply-To field */ - if (InReplyTo) - { - strfcpy (buffer, "In-Reply-To: ", sizeof (buffer)); - mutt_make_string (buffer + 13, sizeof (buffer) - 13, InReplyTo, ctx, cur); - tmp = env->userhdrs; - while (tmp && tmp->next) - tmp = tmp->next; - if (tmp) - { - tmp->next = mutt_new_list (); - tmp = tmp->next; - } - else - tmp = env->userhdrs = mutt_new_list (); - tmp->data = safe_strdup (buffer); - } - + mutt_fix_reply_recipients (env); + mutt_make_misc_reply_headers (env, ctx, cur, curenv); + if(tag) { HEADER *h; @@ -604,25 +649,21 @@ envelope_defaults (ENVELOPE *env, CONTEXT *ctx, HEADER *cur, int flags) env->references = NULL; p = &env->references; - + for(i = 0; i < ctx->vcount; i++) { while(*p) p = &(*p)->next; h = ctx->hdrs[ctx->v2r[i]]; if(h->tagged) - *p = make_references(h->env); + *p = mutt_make_references(h->env); } } else - env->references = make_references(curenv); + env->references = mutt_make_references(curenv); } else if (flags & SENDFORWARD) - { - /* set the default subject for the message. */ - mutt_make_string (buffer, sizeof (buffer), NONULL(ForwFmt), ctx, cur); - env->subject = safe_strdup (buffer); - } + mutt_make_forward_subject (env, ctx, cur); return (0); } @@ -881,7 +922,17 @@ static void encode_descriptions (BODY *b) } } -void +int mutt_resend_message (FILE *fp, CONTEXT *ctx, HEADER *cur) +{ + HEADER *msg = mutt_new_header (); + + if (mutt_prepare_template (fp, ctx, msg, cur, 1) < 0) + return -1; + + return ci_send_message (SENDRESEND, msg, NULL, ctx, cur); +} + +int ci_send_message (int flags, /* send mode */ HEADER *msg, /* template to use for new message */ char *tempfile, /* file specified by -i or -H */ @@ -903,6 +954,8 @@ ci_send_message (int flags, /* send mode */ char *signmic = NULL; #endif + int rv = -1; + if (!flags && !msg && quadoption (OPT_RECALL) != M_NO && mutt_num_postponed (1)) { @@ -910,7 +963,7 @@ ci_send_message (int flags, /* send mode */ * are any postponed messages first. */ if ((i = query_quadoption (OPT_RECALL, _("Recall postponed message?"))) == -1) - return; + return rv; if(i == M_YES) flags |= SENDPOSTPONED; @@ -935,12 +988,20 @@ ci_send_message (int flags, /* send mode */ { msg = mutt_new_header (); +#if 0 + + /* this is no longer used. */ + if (flags == SENDRESEND) { - if (mutt_prepare_template (ctx, msg, cur, 1) < 0) + if (mutt_prepare_template (fp, ctx, msg, cur, 1) < 0) goto cleanup; } - else if (flags == SENDPOSTPONED) + else + +#endif + + if (flags == SENDPOSTPONED) { if ((flags = mutt_get_postponed (ctx, msg, &cur, fcc, sizeof (fcc))) < 0) goto cleanup; @@ -1014,7 +1075,7 @@ ci_send_message (int flags, /* send mode */ } else if (! (flags & (SENDPOSTPONED|SENDRESEND))) { - if ((flags & (SENDREPLY | SENDFORWARD)) && + if ((flags & (SENDREPLY | SENDFORWARD)) && ctx && envelope_defaults (msg->env, ctx, cur, flags) == -1) goto cleanup; @@ -1073,8 +1134,9 @@ ci_send_message (int flags, /* send mode */ - /* include replies/forwarded messages */ - if (generate_body (tempfp, msg, flags, ctx, cur) == -1) + /* include replies/forwarded messages, unless we are given a template */ + if (!tempfile && (ctx || !(flags & (SENDREPLY|SENDFORWARD))) + && generate_body (tempfp, msg, flags, ctx, cur) == -1) goto cleanup; if (! (flags & (SENDMAILX | SENDKEY)) && Editor && mutt_strcmp (Editor, "builtin") != 0) @@ -1089,7 +1151,7 @@ ci_send_message (int flags, /* send mode */ #ifdef _PGPPATH - if (! (flags & SENDKEY)) + if (! (flags & SENDKEY) && tempfp) { #endif @@ -1395,7 +1457,7 @@ full_fcc: if (flags & SENDREPLY) { - if (cur) + if (cur && ctx) mutt_set_flag (ctx, cur, M_REPLIED, 1); else if (!(flags & SENDPOSTPONED) && ctx && ctx->tagged) { @@ -1405,6 +1467,9 @@ full_fcc: } } + + rv = 0; + cleanup: @@ -1430,5 +1495,7 @@ cleanup: if (tempfp) fclose (tempfp); mutt_free_header (&msg); + + return rv; } diff --git a/sendlib.c b/sendlib.c index 8e00634d..00eae548 100644 --- a/sendlib.c +++ b/sendlib.c @@ -1811,49 +1811,53 @@ void mutt_prepare_envelope (ENVELOPE *env) if (!env->message_id) env->message_id = mutt_gen_msgid (); } - -static void _mutt_bounce_message (HEADER *h, ADDRESS *to, const char *resent_from) + +static void _mutt_bounce_message (FILE *fp, HEADER *h, ADDRESS *to, const char *resent_from) { int i; FILE *f; char date[SHORT_STRING], tempfile[_POSIX_PATH_MAX]; - MESSAGE *msg; + MESSAGE *msg = NULL; if (!h) { for (i=0; imsgcount; i++) if (Context->hdrs[i]->tagged) - _mutt_bounce_message (Context->hdrs[i], to, resent_from); + _mutt_bounce_message (fp, Context->hdrs[i], to, resent_from); return; } - if ((msg = mx_open_message (Context, h->msgno)) != NULL) + if (!fp && (msg = mx_open_message (Context, h->msgno)) == NULL) + return; + + if (!fp) fp = msg->fp; + + mutt_mktemp (tempfile); + if ((f = safe_fopen (tempfile, "w")) != NULL) { - mutt_mktemp (tempfile); - if ((f = safe_fopen (tempfile, "w")) != NULL) - { - int ch_flags = CH_XMIT | CH_NONEWLINE; - - if (!option (OPTBOUNCEDELIVERED)) - ch_flags |= CH_WEED_DELIVERED; - - fseek (msg->fp, h->offset, 0); - mutt_copy_header (msg->fp, h, f, ch_flags, NULL); - fprintf (f, "Resent-From: %s", resent_from); - fprintf (f, "\nResent-%s", mutt_make_date (date, sizeof(date))); - fputs ("Resent-To: ", f); - mutt_write_address_list (to, f, 11); - fputc ('\n', f); - mutt_copy_bytes (msg->fp, f, h->content->length); - fclose (f); + int ch_flags = CH_XMIT | CH_NONEWLINE; + + if (!option (OPTBOUNCEDELIVERED)) + ch_flags |= CH_WEED_DELIVERED; + + fseek (fp, h->offset, 0); + mutt_copy_header (fp, h, f, ch_flags, NULL); + fprintf (f, "Resent-From: %s", resent_from); + fprintf (f, "\nResent-%s", mutt_make_date (date, sizeof(date))); + fputs ("Resent-To: ", f); + mutt_write_address_list (to, f, 11); + fputc ('\n', f); + mutt_copy_bytes (fp, f, h->content->length); + fclose (f); - mutt_invoke_sendmail (to, NULL, NULL, tempfile, h->content->encoding == ENC8BIT); - } - mx_close_message (&msg); + mutt_invoke_sendmail (to, NULL, NULL, tempfile, h->content->encoding == ENC8BIT); } + + if (msg) + mx_close_message (&msg); } -void mutt_bounce_message (HEADER *h, ADDRESS *to) +void mutt_bounce_message (FILE *fp, HEADER *h, ADDRESS *to) { ADDRESS *from; const char *fqdn = mutt_fqdn (1); @@ -1870,7 +1874,7 @@ void mutt_bounce_message (HEADER *h, ADDRESS *to) rfc822_write_address (resent_from, sizeof (resent_from), from); rfc822_free_address (&from); - _mutt_bounce_message (h, to, resent_from); + _mutt_bounce_message (fp, h, to, resent_from); } -- 2.49.0