Example #1
0
int mutt_prepare_template (FILE *fp, CONTEXT *ctx, HEADER *newhdr, HEADER *hdr,
			       short weed)
{
  MESSAGE *msg = NULL;
  char file[_POSIX_PATH_MAX];
  BODY *b;
  FILE *bfp;

  int rv = -1;
  STATE s;

  memset (&s, 0, sizeof (s));

  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 */

  fseeko (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);

  /* If message_id is set, then we are resending a message and don't want
   * message_id or mail_followup_to. Otherwise, we are resuming a
   * postponed message, and want to keep the mail_followup_to.
   */
  if (newhdr->env->message_id != NULL)
  {
    FREE (&newhdr->env->message_id);
    FREE (&newhdr->env->mail_followup_to);
  }

  /* decrypt pgp/mime encoded messages */

  if ((WithCrypto & (APPLICATION_PGP|APPLICATION_SMIME) & hdr->security)
      && mutt_is_multipart_encrypted (newhdr->content))
  {
    int ccap = WithCrypto & (APPLICATION_PGP|APPLICATION_SMIME) & hdr->security;
    newhdr->security |= ENCRYPT | ccap;
    if (!crypt_valid_passphrase (ccap))
      goto err;

    mutt_message _("Decrypting message...");
    if (((ccap & APPLICATION_PGP) && crypt_pgp_decrypt_mime (fp, &bfp, newhdr->content, &b) == -1)
	|| ((ccap & APPLICATION_SMIME) && crypt_smime_decrypt_mime (fp, &bfp, newhdr->content, &b) == -1)
	|| b == NULL)
    {
 err:
      mx_close_message (&msg);
      mutt_free_envelope (&newhdr->env);
      mutt_free_body (&newhdr->content);
      mutt_error _("Decryption failed.");
      return -1;
    }

    mutt_free_body (&newhdr->content);
    newhdr->content = b;

    mutt_clear_error ();
  }

  /*
   * remove a potential multipart/signed layer - useful when
   * resending messages
   */

  if (WithCrypto && mutt_is_multipart_signed (newhdr->content))
  {
    newhdr->security |= SIGN;
    if ((WithCrypto & APPLICATION_PGP)
        && ascii_strcasecmp (mutt_get_parameter ("protocol", newhdr->content->parameter), "application/pgp-signature") == 0)
      newhdr->security |= APPLICATION_PGP;
    else if ((WithCrypto & APPLICATION_SMIME))
      newhdr->security |= APPLICATION_SMIME;

    /* destroy the signature */
    mutt_free_body (&newhdr->content->parts->next);
    newhdr->content = mutt_remove_multipart (newhdr->content);
  }


  /*
   * 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);

  s.fpin = bfp;

  /* 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;
    }

    /* set up state flags */

    s.flags = 0;

    if (b->type == TYPETEXT)
    {
      if (!ascii_strcasecmp ("yes", mutt_get_parameter ("x-mutt-noconv", b->parameter)))
	b->noconv = 1;
      else
      {
	s.flags |= M_CHARCONV;
	b->noconv = 0;
      }

      mutt_delete_parameter ("x-mutt-noconv", &b->parameter);
    }

    mutt_adv_mktemp (file, sizeof(file));
    if ((s.fpout = safe_fopen (file, "w")) == NULL)
      goto bail;


    if ((WithCrypto & APPLICATION_PGP)
	&& (mutt_is_application_pgp (b) & (ENCRYPT|SIGN)))
    {

      mutt_body_handler (b, &s);

      newhdr->security |= mutt_is_application_pgp (newhdr->content);

      b->type = TYPETEXT;
      mutt_str_replace (&b->subtype, "plain");
      mutt_delete_parameter ("x-action", &b->parameter);
    }
    else
      mutt_decode_attachment (b, &s);

    if (safe_fclose (&s.fpout) != 0)
      goto bail;

    mutt_str_replace (&b->filename, file);
    b->unlink = 1;

    mutt_stamp_attachment (b);

    mutt_free_body (&b->parts);
    if (b->hdr) b->hdr->content = NULL; /* avoid dangling pointer */
  }

  /* Fix encryption flags. */

  /* No inline if multipart. */
  if (WithCrypto && (newhdr->security & INLINE) && newhdr->content->next)
    newhdr->security &= ~INLINE;

  /* Do we even support multiple mechanisms? */
  newhdr->security &= WithCrypto | ~(APPLICATION_PGP|APPLICATION_SMIME);

  /* Theoretically, both could be set. Take the one the user wants to set by default. */
  if ((newhdr->security & APPLICATION_PGP) && (newhdr->security & APPLICATION_SMIME))
  {
    if (option (OPTSMIMEISDEFAULT))
      newhdr->security &= ~APPLICATION_PGP;
    else
      newhdr->security &= ~APPLICATION_SMIME;
  }

  rv = 0;

  bail:

  /* that's it. */
  if (bfp != fp) safe_fclose (&bfp);
  if (msg) mx_close_message (&msg);

  if (rv == -1)
  {
    mutt_free_envelope (&newhdr->env);
    mutt_free_body (&newhdr->content);
  }

  return rv;
}
Example #2
0
/* returns 1 on success, 0 on error */
int mutt_pipe_attachment (FILE *fp, BODY *b, const char *path, char *outfile)
{
  pid_t thepid;
  int out = -1;
  int rv = 0;
  
  if (outfile && *outfile)
    if ((out = safe_open (outfile, O_CREAT | O_EXCL | O_WRONLY)) < 0)
    {
      mutt_perror ("open");
      return 0;
    }

  mutt_endwin (NULL);

  if (fp)
  {
    /* recv case */

    STATE s;

    memset (&s, 0, sizeof (STATE));

    if (outfile && *outfile)
      thepid = mutt_create_filter_fd (path, &s.fpout, NULL, NULL, -1, out, -1);
    else
      thepid = mutt_create_filter (path, &s.fpout, NULL, NULL);

    if (thepid < 0)
    {
      mutt_perror _("Can't create filter");
      goto bail;
    }
    
    s.fpin = fp;
    mutt_decode_attachment (b, &s);
    safe_fclose (&s.fpout);
  }
  else
  {
    /* send case */

    FILE *ifp, *ofp;

    if ((ifp = fopen (b->filename, "r")) == NULL)
    {
      mutt_perror ("fopen");
      if (outfile && *outfile)
      {
	close (out);
	unlink (outfile);
      }
      return 0;
    }

    if (outfile && *outfile)
      thepid = mutt_create_filter_fd (path, &ofp, NULL, NULL, -1, out, -1);
    else
      thepid = mutt_create_filter (path, &ofp, NULL, NULL);

    if (thepid < 0)
    {
      mutt_perror _("Can't create filter");
      safe_fclose (&ifp);
      goto bail;
    }
    
    mutt_copy_stream (ifp, ofp);
    safe_fclose (&ofp);
    safe_fclose (&ifp);
  }

  rv = 1;
  
bail:
  
  if (outfile && *outfile)
    close (out);

  /*
   * check for error exit from child process
   */
  if (mutt_wait_filter (thepid) != 0)
    rv = 0;

  if (rv == 0 || option (OPTWAITKEY))
    mutt_any_key_to_continue (NULL);
  return rv;
}
Example #3
0
/* 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;
}
Example #4
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 (fp) {
/* Viewing from a received message.
 *
 * Don't use mutt_save_attachment() because we want to perform charset
 * conversion since this will be displayed by the internal pager.
 */
                                STATE decode_state;

                                memset(&decode_state, 0, sizeof(decode_state));
                                decode_state.fpout = safe_fopen(pagerfile, "w");
                                if (!decode_state.fpout) {
                                        dprint(1, (debugfile, "mutt_view_attachment:%d safe_fopen(%s) errno=%d %s\n", __LINE__, pagerfile, errno, strerror(errno)));
                                        mutt_perror(pagerfile);
                                        mutt_sleep(1);
                                        goto return_error;
                                }
                                decode_state.fpin = fp;
                                decode_state.flags = M_CHARCONV;
                                mutt_decode_attachment(a, &decode_state);
                                if (fclose(decode_state.fpout) == EOF)
                                        dprint(1, (debugfile, "mutt_view_attachment:%d fclose errno=%d %s\n", __LINE__, pagerfile, errno, strerror(errno)));
                        }
                        else {
/* in compose mode, just copy the file.  we can't use
 * mutt_decode_attachment() since it assumes the content-encoding has
 * already been applied
 */
                                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;
}