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