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