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