8f59859921d8505e7815b2c6e3ea11c6038d9d0d
[apps/madmutt.git] / recvcmd.c
1 /*
2  * Copyright notice from original mutt:
3  * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.org>
4  *
5  * This file is part of mutt-ng, see http://www.muttng.org/.
6  * It's licensed under the GNU General Public License,
7  * please see the file GPL in the top level source directory.
8  */
9
10 #if HAVE_CONFIG_H
11 # include "config.h"
12 #endif
13
14 #include <lib-lib/mem.h>
15
16 #include "mutt.h"
17 #include "enter.h"
18 #include "state.h"
19 #include "handler.h"
20 #include "recvattach.h"
21 #include "mutt_curses.h"
22 #include "mutt_menu.h"
23 #include "rfc1524.h"
24 #include "mime.h"
25 #include "attach.h"
26 #include "mapping.h"
27 #include "mx.h"
28 #include "copy.h"
29 #include "mutt_idna.h"
30
31 #include "lib/mem.h"
32 #include "lib/intl.h"
33 #include "lib/str.h"
34
35 /* some helper functions to verify that we are exclusively operating
36  * on message/rfc822 attachments
37  */
38
39 static short check_msg (BODY * b, short err)
40 {
41   if (!mutt_is_message_type (b->type, b->subtype)) {
42     if (err)
43       mutt_error _("You may only bounce message/rfc822 parts.");
44
45     return -1;
46   }
47   return 0;
48 }
49
50 static short check_all_msg (ATTACHPTR ** idx, short idxlen,
51                             BODY * cur, short err)
52 {
53   short i;
54
55   if (cur && check_msg (cur, err) == -1)
56     return -1;
57   else if (!cur) {
58     for (i = 0; i < idxlen; i++) {
59       if (idx[i]->content->tagged) {
60         if (check_msg (idx[i]->content, err) == -1)
61           return -1;
62       }
63     }
64   }
65   return 0;
66 }
67
68
69 /* can we decode all tagged attachments? */
70
71 static short check_can_decode (ATTACHPTR ** idx, short idxlen, BODY * cur)
72 {
73   short i;
74
75   if (cur)
76     return mutt_can_decode (cur);
77
78   for (i = 0; i < idxlen; i++)
79     if (idx[i]->content->tagged && !mutt_can_decode (idx[i]->content))
80       return 0;
81
82   return 1;
83 }
84
85 static short count_tagged (ATTACHPTR ** idx, short idxlen)
86 {
87   short count = 0;
88   short i;
89
90   for (i = 0; i < idxlen; i++)
91     if (idx[i]->content->tagged)
92       count++;
93
94   return count;
95 }
96
97 /* count the number of tagged children below a multipart or message
98  * attachment.
99  */
100
101 static short count_tagged_children (ATTACHPTR ** idx, short idxlen, short i)
102 {
103   short level = idx[i]->level;
104   short count = 0;
105
106   while ((++i < idxlen) && (level < idx[i]->level))
107     if (idx[i]->content->tagged)
108       count++;
109
110   return count;
111 }
112 \f
113
114
115 /**
116  **
117  ** The bounce function, from the attachment menu
118  **
119  **/
120
121 void mutt_attach_bounce (FILE * fp, HEADER * hdr,
122                          ATTACHPTR ** idx, short idxlen, BODY * cur)
123 {
124   short i;
125   char prompt[STRING];
126   char buf[HUGE_STRING];
127   char *err = NULL;
128   ADDRESS *adr = NULL;
129   int ret = 0;
130   int p = 0;
131
132   if (check_all_msg (idx, idxlen, cur, 1) == -1)
133     return;
134
135   /* one or more messages? */
136   p = (cur || count_tagged (idx, idxlen) == 1);
137
138   if (p)
139     strfcpy (prompt, _("Bounce message to: "), sizeof (prompt));
140   else
141     strfcpy (prompt, _("Bounce tagged messages to: "), sizeof (prompt));
142
143   buf[0] = '\0';
144   if (mutt_get_field (prompt, buf, sizeof (buf), M_ALIAS)
145       || buf[0] == '\0')
146     return;
147
148   if (!(adr = rfc822_parse_adrlist (adr, buf))) {
149     mutt_error _("Error parsing address!");
150
151     return;
152   }
153
154   adr = mutt_expand_aliases (adr);
155
156   if (mutt_addrlist_to_idna (adr, &err) < 0) {
157     mutt_error (_("Bad IDN: '%s'"), err);
158     p_delete(&err);
159     rfc822_free_address (&adr);
160     return;
161   }
162
163   buf[0] = 0;
164   rfc822_write_address (buf, sizeof (buf), adr, 1);
165
166 #define extra_space (15+7+2)
167   /*
168    * See commands.c.
169    */
170   snprintf (prompt, sizeof (prompt) - 4,
171             (p ? _("Bounce message to %s") : _("Bounce messages to %s")),
172             buf);
173
174   if (mutt_strwidth (prompt) > COLS - extra_space) {
175     mutt_format_string (prompt, sizeof (prompt) - 4,
176                         0, COLS - extra_space, 0, 0,
177                         prompt, sizeof (prompt), 0);
178     str_cat (prompt, sizeof (prompt), "...?");
179   }
180   else
181     str_cat (prompt, sizeof (prompt), "?");
182
183   if (query_quadoption (OPT_BOUNCE, prompt) != M_YES) {
184     rfc822_free_address (&adr);
185     CLEARLINE (LINES - 1);
186     mutt_message (p ? _("Message not bounced.") : _("Messages not bounced."));
187     return;
188   }
189
190   CLEARLINE (LINES - 1);
191
192   if (cur)
193     ret = mutt_bounce_message (fp, cur->hdr, adr);
194   else {
195     for (i = 0; i < idxlen; i++) {
196       if (idx[i]->content->tagged)
197         if (mutt_bounce_message (fp, idx[i]->content->hdr, adr))
198           ret = 1;
199     }
200   }
201
202   if (!ret)
203     mutt_message (p ? _("Message bounced.") : _("Messages bounced."));
204   else
205     mutt_error (p ? _("Error bouncing message!") :
206                 _("Error bouncing messages!"));
207 }
208 \f
209
210
211 /**
212  **
213  ** resend-message, from the attachment menu 
214  **
215  **
216  **/
217
218 void mutt_attach_resend (FILE * fp, HEADER * hdr, ATTACHPTR ** idx,
219                          short idxlen, BODY * cur)
220 {
221   short i;
222
223   if (check_all_msg (idx, idxlen, cur, 1) == -1)
224     return;
225
226   if (cur)
227     mutt_resend_message (fp, Context, cur->hdr);
228   else {
229     for (i = 0; i < idxlen; i++)
230       if (idx[i]->content->tagged)
231         mutt_resend_message (fp, Context, idx[i]->content->hdr);
232   }
233 }
234 \f
235
236 /**
237  **
238  ** forward-message, from the attachment menu 
239  **
240  **/
241
242 /* try to find a common parent message for the tagged attachments. */
243
244 static HEADER *find_common_parent (ATTACHPTR ** idx, short idxlen,
245                                    short nattach)
246 {
247   short i;
248   short nchildren;
249
250   for (i = 0; i < idxlen; i++)
251     if (idx[i]->content->tagged)
252       break;
253
254   while (--i >= 0) {
255     if (mutt_is_message_type
256         (idx[i]->content->type, idx[i]->content->subtype)) {
257       nchildren = count_tagged_children (idx, idxlen, i);
258       if (nchildren == nattach)
259         return idx[i]->content->hdr;
260     }
261   }
262
263   return NULL;
264 }
265
266 /* 
267  * check whether attachment #i is a parent of the attachment
268  * pointed to by cur
269  * 
270  * Note: This and the calling procedure could be optimized quite a 
271  * bit.  For now, it's not worth the effort.
272  */
273
274 static int is_parent (short i, ATTACHPTR ** idx, short idxlen, BODY * cur)
275 {
276   short level = idx[i]->level;
277
278   while ((++i < idxlen) && idx[i]->level > level) {
279     if (idx[i]->content == cur)
280       return 1;
281   }
282
283   return 0;
284 }
285
286 static HEADER *find_parent (ATTACHPTR ** idx, short idxlen, BODY * cur,
287                             short nattach)
288 {
289   short i;
290   HEADER *parent = NULL;
291
292   if (cur) {
293     for (i = 0; i < idxlen; i++) {
294       if (mutt_is_message_type
295           (idx[i]->content->type, idx[i]->content->subtype)
296           && is_parent (i, idx, idxlen, cur))
297         parent = idx[i]->content->hdr;
298       if (idx[i]->content == cur)
299         break;
300     }
301   }
302   else if (nattach)
303     parent = find_common_parent (idx, idxlen, nattach);
304
305   return parent;
306 }
307
308 static void include_header (int quote, FILE * ifp,
309                             HEADER * hdr, FILE * ofp, char *_prefix)
310 {
311   int chflags = CH_DECODE;
312   char prefix[SHORT_STRING];
313
314   if (option (OPTWEED))
315     chflags |= CH_WEED | CH_REORDER;
316
317   if (quote) {
318     if (_prefix)
319       strfcpy (prefix, _prefix, sizeof (prefix));
320     else if (!option (OPTTEXTFLOWED))
321       _mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix),
322                          Context, hdr, 0);
323     else
324       strfcpy (prefix, ">", sizeof (prefix));
325
326     chflags |= CH_PREFIX;
327   }
328
329   mutt_copy_header (ifp, hdr, ofp, chflags, quote ? prefix : NULL);
330 }
331
332 /* Attach all the body parts which can't be decoded. 
333  * This code is shared by forwarding and replying. */
334
335 static BODY **copy_problematic_attachments (FILE * fp,
336                                             BODY ** last,
337                                             ATTACHPTR ** idx,
338                                             short idxlen, short force)
339 {
340   short i;
341
342   for (i = 0; i < idxlen; i++) {
343     if (idx[i]->content->tagged &&
344         (force || !mutt_can_decode (idx[i]->content))) {
345       if (mutt_copy_body (fp, last, idx[i]->content) == -1)
346         return NULL;            /* XXXXX - may lead to crashes */
347       last = &((*last)->next);
348     }
349   }
350   return last;
351 }
352
353 /* 
354  * forward one or several MIME bodies 
355  * (non-message types)
356  */
357
358 static void attach_forward_bodies (FILE * fp, HEADER * hdr,
359                                    ATTACHPTR ** idx, short idxlen,
360                                    BODY * cur, short nattach, int flags)
361 {
362   short i;
363   short mime_fwd_all = 0;
364   short mime_fwd_any = 1;
365   HEADER *parent = NULL;
366   HEADER *tmphdr = NULL;
367   BODY **last;
368   char tmpbody[_POSIX_PATH_MAX];
369   FILE *tmpfp = NULL;
370
371   char prefix[STRING];
372
373   int rc = 0;
374
375   STATE st;
376
377   /* 
378    * First, find the parent message.
379    * Note: This could be made an option by just
380    * putting the following lines into an if block.
381    */
382
383
384   parent = find_parent (idx, idxlen, cur, nattach);
385
386   if (parent == NULL)
387     parent = hdr;
388
389
390   tmphdr = mutt_new_header ();
391   tmphdr->env = mutt_new_envelope ();
392   mutt_make_forward_subject (tmphdr->env, Context, parent);
393
394   mutt_mktemp (tmpbody);
395   if ((tmpfp = safe_fopen (tmpbody, "w")) == NULL) {
396     mutt_error (_("Can't open temporary file %s."), tmpbody);
397     return;
398   }
399
400   mutt_forward_intro (tmpfp, parent);
401
402   /* prepare the prefix here since we'll need it later. */
403
404   if (option (OPTFORWQUOTE)) {
405     if (!option (OPTTEXTFLOWED))
406       _mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix), Context,
407                          parent, 0);
408     else
409       strfcpy (prefix, ">", sizeof (prefix));
410   }
411
412   include_header (option (OPTFORWQUOTE), fp, parent, tmpfp, prefix);
413
414
415   /* 
416    * Now, we have prepared the first part of the message body: The
417    * original message's header. 
418    *
419    * The next part is more interesting: either include the message bodies,
420    * or attach them.
421    */
422
423   if ((!cur || mutt_can_decode (cur)) &&
424       (rc = query_quadoption (OPT_MIMEFWD,
425                               _("Forward as attachments?"))) == M_YES)
426     mime_fwd_all = 1;
427   else if (rc == -1)
428     goto bail;
429
430   /* 
431    * shortcut MIMEFWDREST when there is only one attachment.  Is 
432    * this intuitive?
433    */
434
435   if (!mime_fwd_all && !cur && (nattach > 1)
436       && !check_can_decode (idx, idxlen, cur)) {
437     if ((rc = query_quadoption (OPT_MIMEFWDREST,
438                                 _
439                                 ("Can't decode all tagged attachments.  MIME-forward the others?")))
440         == -1)
441       goto bail;
442     else if (rc == M_NO)
443       mime_fwd_any = 0;
444   }
445
446   /* initialize a state structure */
447
448   memset (&st, 0, sizeof (st));
449
450   if (option (OPTFORWQUOTE))
451     st.prefix = prefix;
452   st.flags = M_CHARCONV;
453   if (option (OPTWEED))
454     st.flags |= M_WEED;
455   st.fpin = fp;
456   st.fpout = tmpfp;
457
458   /* where do we append new MIME parts? */
459   last = &tmphdr->content;
460
461   if (cur) {
462     /* single body case */
463
464     if (!mime_fwd_all && mutt_can_decode (cur)) {
465       mutt_body_handler (cur, &st);
466       state_putc ('\n', &st);
467     }
468     else {
469       if (mutt_copy_body (fp, last, cur) == -1)
470         goto bail;
471       last = &((*last)->next);
472     }
473   }
474   else {
475     /* multiple body case */
476
477     if (!mime_fwd_all) {
478       for (i = 0; i < idxlen; i++) {
479         if (idx[i]->content->tagged && mutt_can_decode (idx[i]->content)) {
480           mutt_body_handler (idx[i]->content, &st);
481           state_putc ('\n', &st);
482         }
483       }
484     }
485
486     if (mime_fwd_any &&
487         (last =
488          copy_problematic_attachments (fp, last, idx, idxlen,
489                                        mime_fwd_all)) == NULL)
490       goto bail;
491   }
492
493   mutt_forward_trailer (tmpfp);
494
495   fclose (tmpfp);
496   tmpfp = NULL;
497
498   /* now that we have the template, send it. */
499   ci_send_message (flags, tmphdr, tmpbody, NULL, parent);
500   return;
501
502 bail:
503
504   if (tmpfp) {
505     fclose (tmpfp);
506     mutt_unlink (tmpbody);
507   }
508
509   mutt_free_header (&tmphdr);
510 }
511
512
513 /* 
514  * Forward one or several message-type attachments. This 
515  * is different from the previous function
516  * since we want to mimic the index menu's behaviour.
517  *
518  * Code reuse from ci_send_message is not possible here -
519  * ci_send_message relies on a context structure to find messages,
520  * while, on the attachment menu, messages are referenced through
521  * the attachment index. 
522  */
523
524 static void attach_forward_msgs (FILE * fp, HEADER * hdr,
525                                  ATTACHPTR ** idx, short idxlen, BODY * cur,
526                                  int flags)
527 {
528   HEADER *curhdr = NULL;
529   HEADER *tmphdr;
530   short i;
531   int rc;
532
533   BODY **last;
534   char tmpbody[_POSIX_PATH_MAX];
535   FILE *tmpfp = NULL;
536
537   int cmflags = 0;
538   int chflags = CH_XMIT;
539
540   if (cur)
541     curhdr = cur->hdr;
542   else {
543     for (i = 0; i < idxlen; i++)
544       if (idx[i]->content->tagged) {
545         curhdr = idx[i]->content->hdr;
546         break;
547       }
548   }
549
550   tmphdr = mutt_new_header ();
551   tmphdr->env = mutt_new_envelope ();
552   mutt_make_forward_subject (tmphdr->env, Context, curhdr);
553
554
555   tmpbody[0] = '\0';
556
557   if ((rc = query_quadoption (OPT_MIMEFWD,
558                               _("Forward MIME encapsulated?"))) == M_NO) {
559
560     /* no MIME encapsulation */
561
562     mutt_mktemp (tmpbody);
563     if (!(tmpfp = safe_fopen (tmpbody, "w"))) {
564       mutt_error (_("Can't create %s."), tmpbody);
565       mutt_free_header (&tmphdr);
566       return;
567     }
568
569     if (option (OPTFORWQUOTE)) {
570       chflags |= CH_PREFIX;
571       cmflags |= M_CM_PREFIX;
572     }
573
574     if (option (OPTFORWDECODE)) {
575       cmflags |= M_CM_DECODE | M_CM_CHARCONV;
576       if (option (OPTWEED)) {
577         chflags |= CH_WEED | CH_REORDER;
578         cmflags |= M_CM_WEED;
579       }
580     }
581
582
583     if (cur) {
584       /* mutt_message_hook (cur->hdr, M_MESSAGEHOOK); */
585       mutt_forward_intro (tmpfp, cur->hdr);
586       _mutt_copy_message (tmpfp, fp, cur->hdr, cur->hdr->content, cmflags,
587                           chflags);
588       mutt_forward_trailer (tmpfp);
589     }
590     else {
591       for (i = 0; i < idxlen; i++) {
592         if (idx[i]->content->tagged) {
593           /* mutt_message_hook (idx[i]->content->hdr, M_MESSAGEHOOK); */
594           mutt_forward_intro (tmpfp, idx[i]->content->hdr);
595           _mutt_copy_message (tmpfp, fp, idx[i]->content->hdr,
596                               idx[i]->content->hdr->content, cmflags,
597                               chflags);
598           mutt_forward_trailer (tmpfp);
599         }
600       }
601     }
602     fclose (tmpfp);
603   }
604   else if (rc == M_YES) {       /* do MIME encapsulation - we don't need to do much here */
605     last = &tmphdr->content;
606     if (cur)
607       mutt_copy_body (fp, last, cur);
608     else {
609       for (i = 0; i < idxlen; i++)
610         if (idx[i]->content->tagged) {
611           mutt_copy_body (fp, last, idx[i]->content);
612           last = &((*last)->next);
613         }
614     }
615   }
616   else
617     mutt_free_header (&tmphdr);
618
619   ci_send_message (flags, tmphdr, *tmpbody ? tmpbody : NULL, NULL, curhdr);
620
621 }
622
623 void mutt_attach_forward (FILE * fp, HEADER * hdr,
624                           ATTACHPTR ** idx, short idxlen, BODY * cur,
625                           int flags)
626 {
627   short nattach;
628
629
630   if (check_all_msg (idx, idxlen, cur, 0) == 0)
631     attach_forward_msgs (fp, hdr, idx, idxlen, cur, flags);
632   else {
633     nattach = count_tagged (idx, idxlen);
634     attach_forward_bodies (fp, hdr, idx, idxlen, cur, nattach, flags);
635   }
636 }
637 \f
638
639
640 /**
641  ** 
642  ** the various reply functions, from the attachment menu
643  **
644  **
645  **/
646
647 /* Create the envelope defaults for a reply.
648  *
649  * This function can be invoked in two ways.
650  * 
651  * Either, parent is NULL.  In this case, all tagged bodies are of a message type,
652  * and the header information is fetched from them.
653  * 
654  * Or, parent is non-NULL.  In this case, cur is the common parent of all the
655  * tagged attachments.
656  * 
657  * Note that this code is horribly similar to envelope_defaults () from send.c.
658  */
659
660 static int
661 attach_reply_envelope_defaults (ENVELOPE * env, ATTACHPTR ** idx,
662                                 short idxlen, HEADER * parent, int flags)
663 {
664   ENVELOPE *curenv = NULL;
665   HEADER *curhdr = NULL;
666   short i;
667
668   if (!parent) {
669     for (i = 0; i < idxlen; i++) {
670       if (idx[i]->content->tagged) {
671         curhdr = idx[i]->content->hdr;
672         curenv = curhdr->env;
673         break;
674       }
675     }
676   }
677   else {
678     curenv = parent->env;
679     curhdr = parent;
680   }
681
682   if (curenv == NULL || curhdr == NULL) {
683     mutt_error _("Can't find any tagged messages.");
684
685     return -1;
686   }
687
688 #ifdef USE_NNTP
689   if ((flags & SENDNEWS)) {
690     /* in case followup set Newsgroups: with Followup-To: if it present */
691     if (!env->newsgroups && curenv &&
692         str_casecmp (curenv->followup_to, "poster"))
693       env->newsgroups = str_dup (curenv->followup_to);
694   }
695   else
696 #endif
697   {
698     if (parent) {
699       if (mutt_fetch_recips (env, curenv, flags) == -1)
700         return -1;
701     }
702     else {
703       for (i = 0; i < idxlen; i++) {
704         if (idx[i]->content->tagged
705             && mutt_fetch_recips (env, idx[i]->content->hdr->env,
706                                   flags) == -1)
707           return -1;
708       }
709     }
710
711     if ((flags & SENDLISTREPLY) && !env->to) {
712       mutt_error _("No mailing lists found!");
713
714       return (-1);
715     }
716
717     mutt_fix_reply_recipients (env);
718   }
719   mutt_make_misc_reply_headers (env, Context, curhdr, curenv);
720
721   if (parent)
722     mutt_add_to_reference_headers (env, curenv, NULL, NULL);
723   else {
724     LIST **p = NULL, **q = NULL;
725
726     for (i = 0; i < idxlen; i++) {
727       if (idx[i]->content->tagged)
728         mutt_add_to_reference_headers (env, idx[i]->content->hdr->env, &p,
729                                        &q);
730     }
731   }
732
733   return 0;
734 }
735
736
737 /*  This is _very_ similar to send.c's include_reply(). */
738
739 static void attach_include_reply (FILE * fp, FILE * tmpfp, HEADER * cur,
740                                   int flags)
741 {
742   int cmflags = M_CM_PREFIX | M_CM_DECODE | M_CM_CHARCONV;
743   int chflags = CH_DECODE;
744
745   /* mutt_message_hook (cur, M_MESSAGEHOOK); */
746
747   mutt_make_attribution (Context, cur, tmpfp);
748
749   if (!option (OPTHEADER))
750     cmflags |= M_CM_NOHEADER;
751   if (option (OPTWEED)) {
752     chflags |= CH_WEED;
753     cmflags |= M_CM_WEED;
754   }
755
756   _mutt_copy_message (tmpfp, fp, cur, cur->content, cmflags, chflags);
757   mutt_make_post_indent (Context, cur, tmpfp);
758 }
759
760 void mutt_attach_reply (FILE * fp, HEADER * hdr,
761                         ATTACHPTR ** idx, short idxlen, BODY * cur, int flags)
762 {
763   short mime_reply_any = 0;
764
765   short nattach = 0;
766   HEADER *parent = NULL;
767   HEADER *tmphdr = NULL;
768   short i;
769
770   STATE st;
771   char tmpbody[_POSIX_PATH_MAX];
772   FILE *tmpfp;
773
774   char prefix[SHORT_STRING];
775   int rc;
776
777 #ifdef USE_NNTP
778   if (flags & SENDNEWS)
779     set_option (OPTNEWSSEND);
780   else
781     unset_option (OPTNEWSSEND);
782 #endif
783
784   if (check_all_msg (idx, idxlen, cur, 0) == -1) {
785     nattach = count_tagged (idx, idxlen);
786     if ((parent = find_parent (idx, idxlen, cur, nattach)) == NULL)
787       parent = hdr;
788   }
789
790   if (nattach > 1 && !check_can_decode (idx, idxlen, cur)) {
791     if ((rc = query_quadoption (OPT_MIMEFWDREST,
792                                 _
793                                 ("Can't decode all tagged attachments.  MIME-encapsulate the others?")))
794         == -1)
795       return;
796     else if (rc == M_YES)
797       mime_reply_any = 1;
798   }
799   else if (nattach == 1)
800     mime_reply_any = 1;
801
802   tmphdr = mutt_new_header ();
803   tmphdr->env = mutt_new_envelope ();
804
805   if (attach_reply_envelope_defaults (tmphdr->env, idx, idxlen,
806                                       parent ? parent : (cur ? cur->
807                                                          hdr : NULL),
808                                       flags) == -1) {
809     mutt_free_header (&tmphdr);
810     return;
811   }
812
813   mutt_mktemp (tmpbody);
814   if ((tmpfp = safe_fopen (tmpbody, "w")) == NULL) {
815     mutt_error (_("Can't create %s."), tmpbody);
816     mutt_free_header (&tmphdr);
817     return;
818   }
819
820   if (!parent) {
821     if (cur)
822       attach_include_reply (fp, tmpfp, cur->hdr, flags);
823     else {
824       for (i = 0; i < idxlen; i++) {
825         if (idx[i]->content->tagged)
826           attach_include_reply (fp, tmpfp, idx[i]->content->hdr, flags);
827       }
828     }
829   }
830   else {
831     mutt_make_attribution (Context, parent, tmpfp);
832
833     memset (&st, 0, sizeof (STATE));
834     st.fpin = fp;
835     st.fpout = tmpfp;
836
837     if (!option (OPTTEXTFLOWED))
838       _mutt_make_string (prefix, sizeof (prefix), NONULL (Prefix),
839                          Context, parent, 0);
840     else
841       strfcpy (prefix, ">", sizeof (prefix));
842
843     st.prefix = prefix;
844     st.flags = M_CHARCONV;
845
846     if (option (OPTWEED))
847       st.flags |= M_WEED;
848
849     if (option (OPTHEADER))
850       include_header (1, fp, parent, tmpfp, prefix);
851
852     if (cur) {
853       if (mutt_can_decode (cur)) {
854         mutt_body_handler (cur, &st);
855         state_putc ('\n', &st);
856       }
857       else
858         mutt_copy_body (fp, &tmphdr->content, cur);
859     }
860     else {
861       for (i = 0; i < idxlen; i++) {
862         if (idx[i]->content->tagged && mutt_can_decode (idx[i]->content)) {
863           mutt_body_handler (idx[i]->content, &st);
864           state_putc ('\n', &st);
865         }
866       }
867     }
868
869     mutt_make_post_indent (Context, parent, tmpfp);
870
871     if (mime_reply_any && !cur &&
872         copy_problematic_attachments (fp, &tmphdr->content, idx, idxlen,
873                                       0) == NULL) {
874       mutt_free_header (&tmphdr);
875       fclose (tmpfp);
876       return;
877     }
878   }
879
880   fclose (tmpfp);
881
882   if (ci_send_message (flags, tmphdr, tmpbody, NULL, parent) == 0)
883     mutt_set_flag (Context, hdr, M_REPLIED, 1);
884 }