static short check_msg (struct body * b, short err) { if (!mutt_is_message_type (b->type, b->subtype)) { if (err) mutt_error("You may only bounce message/rfc822 parts."); return -1; } return 0; }
static struct header *find_parent (ATTACHPTR **idx, short idxlen, struct body *cur, short nattach) { short i; struct header *parent = NULL; if (cur) { for (i = 0; i < idxlen; i++) { if (mutt_is_message_type (idx[i]->content->type, idx[i]->content->subtype) && is_parent (i, idx, idxlen, cur)) parent = idx[i]->content->hdr; if (idx[i]->content == cur) break; } } else if (nattach) parent = find_common_parent (idx, idxlen, nattach); return parent; }
static HEADER *find_common_parent (ATTACHPTR ** idx, short idxlen, short nattach) { short i; short nchildren; for (i = 0; i < idxlen; i++) if (idx[i]->content->tagged) break; while (--i >= 0) { if (mutt_is_message_type (idx[i]->content->type, idx[i]->content->subtype)) { nchildren = count_tagged_children (idx, idxlen, i); if (nchildren == nattach) return idx[i]->content->hdr; } } return NULL; }
/* returns 0 on success, -1 on error */ int mutt_save_attachment (FILE *fp, BODY *m, char *path, int flags, HEADER *hdr) { if (fp) { /* recv mode */ if(hdr && m->hdr && m->encoding != ENCBASE64 && m->encoding != ENCQUOTEDPRINTABLE && mutt_is_message_type(m->type, m->subtype)) { /* message type attachments are written to mail folders. */ char buf[HUGE_STRING]; HEADER *hn; CONTEXT ctx; MESSAGE *msg; int chflags = 0; int r = -1; hn = m->hdr; hn->msgno = hdr->msgno; /* required for MH/maildir */ hn->read = 1; fseeko (fp, m->offset, 0); if (fgets (buf, sizeof (buf), fp) == NULL) return -1; if (mx_open_mailbox(path, M_APPEND | M_QUIET, &ctx) == NULL) return -1; if ((msg = mx_open_new_message (&ctx, hn, is_from (buf, NULL, 0, NULL) ? 0 : M_ADD_FROM)) == NULL) { mx_close_mailbox(&ctx, NULL); return -1; } if (ctx.magic == M_MBOX || ctx.magic == M_MMDF) chflags = CH_FROM | CH_UPDATE_LEN; chflags |= (ctx.magic == M_MAILDIR ? CH_NOSTATUS : CH_UPDATE); if (_mutt_copy_message (msg->fp, fp, hn, hn->content, 0, chflags) == 0 && mx_commit_message (msg, &ctx) == 0) r = 0; else r = -1; mx_close_message (&msg); mx_close_mailbox (&ctx, NULL); return r; } else { /* In recv mode, extract from folder and decode */ STATE s; memset (&s, 0, sizeof (s)); s.flags |= M_CHARCONV; if ((s.fpout = mutt_save_attachment_open (path, flags)) == NULL) { mutt_perror ("fopen"); mutt_sleep (2); return (-1); } fseeko ((s.fpin = fp), m->offset, 0); mutt_decode_attachment (m, &s); if (fclose (s.fpout) != 0) { mutt_perror ("fclose"); mutt_sleep (2); return (-1); } } } else { /* In send mode, just copy file */ FILE *ofp, *nfp; if ((ofp = fopen (m->filename, "r")) == NULL) { mutt_perror ("fopen"); return (-1); } if ((nfp = mutt_save_attachment_open (path, flags)) == NULL) { mutt_perror ("fopen"); safe_fclose (&ofp); return (-1); } if (mutt_copy_stream (ofp, nfp) == -1) { mutt_error _("Write fault!"); safe_fclose (&ofp); safe_fclose (&nfp); return (-1); } safe_fclose (&ofp); safe_fclose (&nfp); } 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; }