]> granicus.if.org Git - mutt/commitdiff
Rewriting lots of the recvattach code.
authorThomas Roessler <roessler@does-not-exist.org>
Sun, 7 Nov 1999 22:19:45 +0000 (22:19 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Sun, 7 Nov 1999 22:19:45 +0000 (22:19 +0000)
21 files changed:
Makefile.am
attach.c
attach.h
browser.c
commands.c
compose.c
curs_main.c
functions.h
init.h
mutt.h
muttlib.c
pager.c
pager.h
postpone.c
protos.h
recvattach.c
recvcmd.c [new file with mode: 0644]
rfc1524.c
rfc1524.h
send.c
sendlib.c

index 4a6f3b933f98c92d25ab2f5558a5ed8788e169b1..d0ff659ca6af1a812da01ea8a2e2427fb91280bb 100644 (file)
@@ -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 \
index ea77dd042aa40a7df0546087f539939d5bbba399..ebc83df0754df24072c2f29e91bf7d85e0789542 100644 (file)
--- 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);
   }
index 32e9d0d510eea7ceb47b016af6ba0a46ca8bafa3..dee07efb995321eb5ebc459cdbc051c3404e912e 100644 (file)
--- 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);
index b51746c37dbdfe2720af3dc14f873d914f45e816..14c1089bd6d88d862245dc1803c6cef302355050 100644 (file)
--- 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;
          }
index b0ef9a6b1984a35bda58f411ab7dc4daf60041bc..219d46da5ac272a7ece5a0a3931ed364b69c2d1a 100644 (file)
@@ -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."));
 }
index 3a7df73700ace196baf5e51d0b945371afcd514f..afef5da8cf89272686ef7a4b50a7312115700a71 100644 (file)
--- 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;
index d0c995879bf0ab3fdd56ccbfefa7fbafb3c2c399..5bdf8a40f5f11968457432a069ffdc8b82bf5c71 100644 (file)
@@ -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;
index 92c439e64adacfc3c9fc7e7b23ec2d1309b17f2c..5bac5774ef37d023bc64e9734cd357a01e69b087 100644 (file)
@@ -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 5e334a96ac63b1633405571b77ccbaa5151acde2..e47aedf150123dd259eb8c91f8a1ba66a00371be 100644 (file)
--- 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 46e7803d1f80a0e1046c498bb26b06d3dcbe14c4..2e19ee32409b9496610af05a725aedb79ce92ddc 100644 (file)
--- 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,
index 1b9958037dbedd05ca3f069e63e6431d1dcbe036..ee388af246ef899ab68d12a66dede836f9b74850 100644 (file)
--- 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 03bbb635db4bfbc6b0e337a726377f2fb2dd2f1e..9ac706bca13784d5505d9f525884f35382481780 100644 (file)
--- a/pager.c
+++ b/pager.c
 #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 b81d5ea5b70b5b342865e688d26ee09b60df36f8..1761ab338878c998a559af0cb73245b9e3f19a0e 100644 (file)
--- 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 *);
index c159322d7a001d450ea0c87647c077cfbba2440a..7ad73fb763c56c9008715bd399f00bf638d0023d 100644 (file)
@@ -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;
 }
index c1dd427c969420113cda383a6442fcf7644e649c..8a8c2ac72753d574723e85fb8e8a2fcbb52257fa 100644 (file)
--- 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 *);
 
 
index da82819d23639c78f3268f7a281e285054be1193..3d72d64376d2d023d967c2333bfd691ec87d6d29 100644 (file)
@@ -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 (file)
index 0000000..8dff3ba
--- /dev/null
+++ b/recvcmd.c
@@ -0,0 +1,873 @@
+/*
+ * Copyright (C) 1999   Thomas Roessler <roessler@guug.de>
+ * 
+ *     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;
+}
+
+
+\f
+/**
+ **
+ ** 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);
+}
+
+
+\f
+/**
+ **
+ ** 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);
+  }
+}
+
+\f
+/**
+ **
+ ** 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);
+  }
+}
+
+
+\f
+/**
+ ** 
+ ** 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);
+}
+
index 6f803dbca032b49ec09426cd4e68244c8ad137e9..39181880d5266ad8e8bcff386a0e05760202b0a0 100644 (file)
--- 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.
index 1051f111233bb31e833859d76a8e0f78f8dbdc3f..38f5bc492b053862384b04444a04286f31c6f717 100644 (file)
--- 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 afa4c74d11ad70cc444f80bc9aea7271479bc838..4d880cc119ef1699069d282732196a51c4ab4053 100644 (file)
--- 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;
 
 }
index 8e00634d3585b34e3063338c6a8d0b0e1e7eee77..00eae548b26e99e5168bba3ae93e51aa8a28ccfa 100644 (file)
--- 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; i<Context->msgcount; 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);
 }