int mutt_copy_body (FILE *fp, BODY **tgt, BODY *src) { char tmp[_POSIX_PATH_MAX]; BODY *b; PARAMETER *par, **ppar; short use_disp; if (src->filename) { use_disp = 1; strfcpy (tmp, src->filename, sizeof (tmp)); } else { use_disp = 0; tmp[0] = '\0'; } mutt_adv_mktemp (tmp, sizeof (tmp)); if (mutt_save_attachment (fp, src, tmp, 0, NULL) == -1) return -1; *tgt = mutt_new_body (); b = *tgt; memcpy (b, src, sizeof (BODY)); b->parts = NULL; b->next = NULL; b->hdr = NULL; b->filename = safe_strdup (tmp); b->use_disp = use_disp; b->unlink = 1; if (mutt_is_text_type (b->type, b->subtype)) b->noconv = 1; b->xtype = safe_strdup (b->xtype); b->subtype = safe_strdup (b->subtype); b->form_name = safe_strdup (b->form_name); b->filename = safe_strdup (b->filename); b->d_filename = safe_strdup (b->d_filename); b->description = safe_strdup (b->description); /* copy parameters */ for (par = b->parameter, ppar = &b->parameter; par; ppar = &(*ppar)->next, par = par->next) { *ppar = mutt_new_parameter (); (*ppar)->attribute = safe_strdup (par->attribute); (*ppar)->value = safe_strdup (par->value); } mutt_stamp_attachment (b); return 0; }
int mutt_print_attachment (FILE *fp, BODY *a) { char newfile[_POSIX_PATH_MAX] = ""; char type[STRING]; pid_t thepid; FILE *ifp, *fpout; short unlink_newfile = 0; snprintf (type, sizeof (type), "%s/%s", TYPE (a), a->subtype); if (rfc1524_mailcap_lookup (a, type, NULL, M_PRINT)) { char command[_POSIX_PATH_MAX+STRING]; rfc1524_entry *entry; int piped = FALSE; dprint (2, (debugfile, "Using mailcap...\n")); entry = rfc1524_new_entry (); rfc1524_mailcap_lookup (a, type, entry, M_PRINT); if (rfc1524_expand_filename (entry->nametemplate, a->filename, newfile, sizeof (newfile))) { if (!fp) { if (safe_symlink(a->filename, newfile) == -1) { if (mutt_yesorno (_("Can't match nametemplate, continue?"), M_YES) != M_YES) { rfc1524_free_entry (&entry); return 0; } strfcpy (newfile, a->filename, sizeof (newfile)); } else unlink_newfile = 1; } } /* in recv mode, save file to newfile first */ if (fp) mutt_save_attachment (fp, a, newfile, 0, NULL); strfcpy (command, entry->printcommand, sizeof (command)); piped = rfc1524_expand_command (a, newfile, type, command, sizeof (command)); mutt_endwin (NULL); /* interactive program */ if (piped) { if ((ifp = fopen (newfile, "r")) == NULL) { mutt_perror ("fopen"); rfc1524_free_entry (&entry); return (0); } if ((thepid = mutt_create_filter (command, &fpout, NULL, NULL)) < 0) { mutt_perror _("Can't create filter"); rfc1524_free_entry (&entry); safe_fclose (&ifp); return 0; } mutt_copy_stream (ifp, fpout); safe_fclose (&fpout); safe_fclose (&ifp); if (mutt_wait_filter (thepid) || option (OPTWAITKEY)) mutt_any_key_to_continue (NULL); } else { if (mutt_system (command) || option (OPTWAITKEY)) mutt_any_key_to_continue (NULL); } if (fp) mutt_unlink (newfile); else if (unlink_newfile) unlink(newfile); rfc1524_free_entry (&entry); return (1); } if (!ascii_strcasecmp ("text/plain", type) || !ascii_strcasecmp ("application/postscript", type)) { return (mutt_pipe_attachment (fp, a, NONULL(PrintCmd), NULL)); } else if (mutt_can_decode (a)) { /* decode and print */ int rc = 0; ifp = NULL; fpout = NULL; mutt_mktemp (newfile, sizeof (newfile)); if (mutt_decode_save_attachment (fp, a, newfile, M_PRINTING, 0) == 0) { dprint (2, (debugfile, "successfully decoded %s type attachment to %s\n", type, newfile)); if ((ifp = fopen (newfile, "r")) == NULL) { mutt_perror ("fopen"); goto bail0; } dprint (2, (debugfile, "successfully opened %s read-only\n", newfile)); mutt_endwin (NULL); if ((thepid = mutt_create_filter (NONULL(PrintCmd), &fpout, NULL, NULL)) < 0) { mutt_perror _("Can't create filter"); goto bail0; } dprint (2, (debugfile, "Filter created.\n")); mutt_copy_stream (ifp, fpout); safe_fclose (&fpout); safe_fclose (&ifp); if (mutt_wait_filter (thepid) != 0 || option (OPTWAITKEY)) mutt_any_key_to_continue (NULL); rc = 1; } bail0: safe_fclose (&ifp); safe_fclose (&fpout); mutt_unlink (newfile); return rc; } else { mutt_error _("I don't know how to print that!"); return 0; } }
/* returns -1 on error, 0 or the return code from mutt_do_pager() on success */ int mutt_view_attachment (FILE *fp, BODY *a, int flag, HEADER *hdr, ATTACHPTR **idx, short idxlen) { char tempfile[_POSIX_PATH_MAX] = ""; char pagerfile[_POSIX_PATH_MAX] = ""; int is_message; int use_mailcap; int use_pipe = 0; int use_pager = 1; char type[STRING]; char command[HUGE_STRING]; char descrip[STRING]; char *fname; rfc1524_entry *entry = NULL; int rc = -1; int unlink_tempfile = 0; is_message = mutt_is_message_type(a->type, a->subtype); if (WithCrypto && is_message && a->hdr && (a->hdr->security & ENCRYPT) && !crypt_valid_passphrase(a->hdr->security)) return (rc); use_mailcap = (flag == M_MAILCAP || (flag == M_REGULAR && mutt_needs_mailcap (a))); snprintf (type, sizeof (type), "%s/%s", TYPE (a), a->subtype); if (use_mailcap) { entry = rfc1524_new_entry (); if (!rfc1524_mailcap_lookup (a, type, entry, 0)) { if (flag == M_REGULAR) { /* fallback to view as text */ rfc1524_free_entry (&entry); mutt_error _("No matching mailcap entry found. Viewing as text."); flag = M_AS_TEXT; use_mailcap = 0; } else goto return_error; } } if (use_mailcap) { if (!entry->command) { mutt_error _("MIME type not defined. Cannot view attachment."); goto return_error; } strfcpy (command, entry->command, sizeof (command)); if (fp) { fname = safe_strdup (a->filename); mutt_sanitize_filename (fname, 1); } else fname = a->filename; if (rfc1524_expand_filename (entry->nametemplate, fname, tempfile, sizeof (tempfile))) { if (fp == NULL && mutt_strcmp(tempfile, a->filename)) { /* send case: the file is already there */ if (safe_symlink (a->filename, tempfile) == -1) { if (mutt_yesorno (_("Can't match nametemplate, continue?"), M_YES) == M_YES) strfcpy (tempfile, a->filename, sizeof (tempfile)); else goto return_error; } else unlink_tempfile = 1; } } else if (fp == NULL) /* send case */ strfcpy (tempfile, a->filename, sizeof (tempfile)); if (fp) { /* recv case: we need to save the attachment to a file */ FREE (&fname); if (mutt_save_attachment (fp, a, tempfile, 0, NULL) == -1) goto return_error; } use_pipe = rfc1524_expand_command (a, tempfile, type, command, sizeof (command)); use_pager = entry->copiousoutput; } if (use_pager) { if (fp && !use_mailcap && a->filename) { /* recv case */ strfcpy (pagerfile, a->filename, sizeof (pagerfile)); mutt_adv_mktemp (pagerfile, sizeof(pagerfile)); } else mutt_mktemp (pagerfile, sizeof (pagerfile)); } if (use_mailcap) { pid_t thepid = 0; int tempfd = -1, pagerfd = -1; if (!use_pager) mutt_endwin (NULL); if (use_pager || use_pipe) { if (use_pager && ((pagerfd = safe_open (pagerfile, O_CREAT | O_EXCL | O_WRONLY)) == -1)) { mutt_perror ("open"); goto return_error; } if (use_pipe && ((tempfd = open (tempfile, 0)) == -1)) { if(pagerfd != -1) close(pagerfd); mutt_perror ("open"); goto return_error; } if ((thepid = mutt_create_filter_fd (command, NULL, NULL, NULL, use_pipe ? tempfd : -1, use_pager ? pagerfd : -1, -1)) == -1) { if(pagerfd != -1) close(pagerfd); if(tempfd != -1) close(tempfd); mutt_error _("Cannot create filter"); goto return_error; } if (use_pager) { if (a->description) snprintf (descrip, sizeof (descrip), _("---Command: %-20.20s Description: %s"), command, a->description); else snprintf (descrip, sizeof (descrip), _("---Command: %-30.30s Attachment: %s"), command, type); } if ((mutt_wait_filter (thepid) || (entry->needsterminal && option (OPTWAITKEY))) && !use_pager) mutt_any_key_to_continue (NULL); if (tempfd != -1) close (tempfd); if (pagerfd != -1) close (pagerfd); } else { /* interactive command */ if (mutt_system (command) || (entry->needsterminal && option (OPTWAITKEY))) mutt_any_key_to_continue (NULL); } } else { /* Don't use mailcap; the attachment is viewed in the pager */ if (flag == M_AS_TEXT) { /* just let me see the raw data */ if (mutt_save_attachment (fp, a, pagerfile, 0, NULL)) goto return_error; } else { /* Use built-in handler */ set_option (OPTVIEWATTACH); /* disable the "use 'v' to view this part" * message in case of error */ if (mutt_decode_save_attachment (fp, a, pagerfile, M_DISPLAY, 0)) { unset_option (OPTVIEWATTACH); goto return_error; } unset_option (OPTVIEWATTACH); } if (a->description) strfcpy (descrip, a->description, sizeof (descrip)); else if (a->filename) snprintf (descrip, sizeof (descrip), _("---Attachment: %s: %s"), a->filename, type); else snprintf (descrip, sizeof (descrip), _("---Attachment: %s"), type); } /* We only reach this point if there have been no errors */ if (use_pager) { pager_t info; memset (&info, 0, sizeof (info)); info.fp = fp; info.bdy = a; info.ctx = Context; info.idx = idx; info.idxlen = idxlen; info.hdr = hdr; rc = mutt_do_pager (descrip, pagerfile, M_PAGER_ATTACHMENT | (is_message ? M_PAGER_MESSAGE : 0), &info); *pagerfile = '\0'; } else rc = 0; return_error: if (entry) rfc1524_free_entry (&entry); if (fp && tempfile[0]) mutt_unlink (tempfile); else if (unlink_tempfile) unlink(tempfile); if (pagerfile[0]) mutt_unlink (pagerfile); return rc; }
int mutt_prepare_template (FILE *fp, CONTEXT *ctx, HEADER *newhdr, HEADER *hdr, short weed) { MESSAGE *msg = NULL; char file[_POSIX_PATH_MAX]; LIST *p, **q; BODY *b; FILE *bfp; if (!fp && (msg = mx_open_message (ctx, hdr->msgno)) == NULL) return (-1); if (!fp) fp = msg->fp; bfp = fp; /* parse the message header and MIME structure */ fseek (fp, hdr->offset, 0); newhdr->offset = hdr->offset; newhdr->env = mutt_read_rfc822_header (fp, newhdr, 1, weed); newhdr->content->length = hdr->content->length; mutt_parse_part (fp, newhdr->content); /* weed user-agent, x-mailer - we don't want them here */ p = newhdr->env->userhdrs; q = &newhdr->env->userhdrs; while (p) { if (!strncasecmp (p->data, "x-mailer:", 9) || !strncasecmp (p->data, "user-agent:", 11)) { *q = p->next; p->next = NULL; mutt_free_list (&p); } else q = &p->next; p = *q; } safe_free ((void **) &newhdr->env->message_id); safe_free ((void **) &newhdr->env->mail_followup_to); #ifdef HAVE_PGP /* decrypt pgp/mime encoded messages */ if ((hdr->pgp & PGPENCRYPT) && mutt_is_multipart_encrypted (newhdr->content)) { newhdr->pgp |= PGPENCRYPT; if (!pgp_valid_passphrase()) goto err; mutt_message _("Invoking PGP..."); if (pgp_decrypt_mime (fp, &bfp, newhdr->content, &b) == -1) { err: mx_close_message (&msg); mutt_free_envelope (&newhdr->env); mutt_free_body (&newhdr->content); return -1; } mutt_free_body (&newhdr->content); newhdr->content = b; mutt_clear_error (); } /* * remove a potential multipart/signed layer - useful when * resending messages */ if (mutt_is_multipart_signed (newhdr->content)) { newhdr->pgp |= PGPSIGN; /* destroy the signature */ mutt_free_body (&newhdr->content->parts->next); newhdr->content = mutt_remove_multipart (newhdr->content); } #endif /* * We don't need no primary multipart. * Note: We _do_ preserve messages! * * XXX - we don't handle multipart/alternative in any * smart way when sending messages. However, one may * consider this a feature. * */ if (newhdr->content->type == TYPEMULTIPART) newhdr->content = mutt_remove_multipart (newhdr->content); /* create temporary files for all attachments */ for (b = newhdr->content; b; b = b->next) { /* what follows is roughly a receive-mode variant of * mutt_get_tmp_attachment () from muttlib.c */ file[0] = '\0'; if (b->filename) { strfcpy (file, b->filename, sizeof (file)); b->d_filename = safe_strdup (b->filename); } else /* avoid Content-Disposition: header with temporary filename */ b->use_disp = 0; mutt_adv_mktemp (file, sizeof(file)); if (mutt_save_attachment (bfp, b, file, 0, NULL) == -1) { mutt_free_envelope (&newhdr->env); mutt_free_body (&newhdr->content); if (bfp != fp) fclose (bfp); if (msg) mx_close_message (&msg); return -1; } mutt_str_replace (&b->filename, file); b->unlink = 1; if (mutt_is_text_type (b->type, b->subtype)) b->noconv = 1; mutt_stamp_attachment (b); mutt_free_body (&b->parts); if (b->hdr) b->hdr->content = NULL; /* avoid dangling pointer */ } /* that's it. */ if (bfp != fp) fclose (bfp); if (msg) mx_close_message (&msg); return 0; }