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