Ejemplo n.º 1
0
void mutt_free_header (HEADER **h)
{
  if(!h || !*h) return;
  mutt_free_envelope (&(*h)->env);
  mutt_free_body (&(*h)->content);
  safe_free ((void **) &(*h)->tree);
  safe_free ((void **) &(*h)->path);
#ifdef MIXMASTER
  mutt_free_list (&(*h)->chain);
#endif
  safe_free ((void **) h);
}
Ejemplo n.º 2
0
void mutt_free_header (HEADER ** h)
{
  if (!h || !*h)
    return;
  mutt_free_envelope (&(*h)->env);
  mutt_free_body (&(*h)->content);
  mem_free (&(*h)->maildir_flags);
  mem_free (&(*h)->tree);
  mem_free (&(*h)->path);
#ifdef MIXMASTER
  mutt_free_list (&(*h)->chain);
#endif
#if defined USE_POP || defined USE_IMAP || defined USE_NNTP
  mem_free (&(*h)->data);
#endif
  mem_free (h);
}
Ejemplo n.º 3
0
/* move all the headers from extra not present in base into base */
void mutt_merge_envelopes(ENVELOPE* base, ENVELOPE** extra)
{
  /* copies each existing element if necessary, and sets the element
  * to NULL in the source so that mutt_free_envelope doesn't leave us
  * with dangling pointers. */
#define MOVE_ELEM(h) if (!base->h) { base->h = (*extra)->h; (*extra)->h = NULL; }
  MOVE_ELEM(return_path);
  MOVE_ELEM(from);
  MOVE_ELEM(to);
  MOVE_ELEM(cc);
  MOVE_ELEM(bcc);
  MOVE_ELEM(sender);
  MOVE_ELEM(reply_to);
  MOVE_ELEM(mail_followup_to);
  MOVE_ELEM(list_post);
  MOVE_ELEM(message_id);
  MOVE_ELEM(supersedes);
  MOVE_ELEM(date);
  MOVE_ELEM(x_label);
  if (!base->refs_changed) {
    MOVE_ELEM(references);
  }
  if (!base->irt_changed) {
    MOVE_ELEM(in_reply_to);
  }
  /* real_subj is subordinate to subject */
  if (!base->subject) {
    base->subject = (*extra)->subject;
    base->real_subj = (*extra)->real_subj;
    (*extra)->subject = NULL;
    (*extra)->real_subj = NULL;
  }
  /* spam and user headers should never be hashed, and the new envelope may
   * have better values. Use new versions regardless. */
  mutt_buffer_free (&base->spam);
  mutt_free_list (&base->userhdrs);
  MOVE_ELEM(spam);
  MOVE_ELEM(userhdrs);
#undef MOVE_ELEM
  
  mutt_free_envelope(extra);
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
void mutt_edit_headers (const char *editor,
			const char *body,
			HEADER *msg,
			char *fcc,
			size_t fcclen)
{
  char path[_POSIX_PATH_MAX];	/* tempfile used to edit headers + body */
  char buffer[LONG_STRING];
  char *p;
  FILE *ifp, *ofp;
  int i, keep;
  int in_reply_to = 0;	/* did we see the in-reply-to field ? */
  ENVELOPE *n;
  time_t mtime;
  struct stat st;
  LIST *cur, *last = NULL, *tmp;

  mutt_mktemp (path);
  if ((ofp = safe_fopen (path, "w")) == NULL)
  {
    mutt_perror (path);
    return;
  }

  mutt_write_rfc822_header (ofp, msg->env, NULL, 1, 0);
  fputc ('\n', ofp);	/* tie off the header. */

  /* now copy the body of the message. */
  if ((ifp = fopen (body, "r")) == NULL)
  {
    mutt_perror (body);
    return;
  }

  mutt_copy_stream (ifp, ofp);

  fclose (ifp);
  fclose (ofp);

  if (stat (path, &st) == -1)
  {
    mutt_perror (path);
    return;
  }

  mtime = st.st_mtime;
  mutt_edit_file (editor, path);
  stat (path, &st);
  if (mtime == st.st_mtime)
  {
    dprint (1, (debugfile, "ci_edit_headers(): temp file was not modified.\n"));
    /* the file has not changed! */
    mutt_unlink (path);
    return;
  }

  mutt_unlink (body);
  mutt_free_list (&msg->env->userhdrs);

  /* Read the temp file back in */
  if ((ifp = fopen (path, "r")) == NULL)
  {
    mutt_perror (path);
    return;
  }
  
  if ((ofp = safe_fopen (body, "w")) == NULL)
  {
    /* intentionally leak a possible temporary file here */
    fclose (ifp);
    mutt_perror (body);
    return;
  }
  
  n = mutt_read_rfc822_header (ifp, NULL, 1, 0);
  while ((i = fread (buffer, 1, sizeof (buffer), ifp)) > 0)
    fwrite (buffer, 1, i, ofp);
  fclose (ofp);
  fclose (ifp);
  mutt_unlink (path);

  /* restore old info. */
  n->references = msg->env->references;
  msg->env->references = NULL;
  mutt_free_envelope (&msg->env);
  msg->env = n;

  mutt_expand_aliases_env (msg->env);
  
  /* search through the user defined headers added to see if either a 
   * fcc: or attach-file: field was specified.  
   */

  cur = msg->env->userhdrs;
  while (cur)
  {
    keep = 1;

    /* keep track of whether or not we see the in-reply-to field.  if we did
     * not, remove the references: field later so that we can generate a new
     * message based upon this one.
     */
    if (mutt_strncasecmp ("in-reply-to. good thing you replied:", cur->data, 12) == 0)
      in_reply_to = 1;
    else if (fcc && mutt_strncasecmp ("fcc:", cur->data, 4) == 0)
    {
      p = cur->data + 4;
      SKIPWS (p);
      if (*p)
      {
	strfcpy (fcc, p, fcclen);
	mutt_pretty_mailbox (fcc);
      }
      keep = 0;
    }
    else if (mutt_strncasecmp ("attach file:", cur->data, 7) == 0)
    {
      BODY *body;
      BODY *parts;
      char *q;

      p = cur->data + 7;
      SKIPWS (p);
      if (*p)
      {
	if ((q = strpbrk (p, " \t")))
	{
	  mutt_substrcpy (path, p, q, sizeof (path));
	  SKIPWS (q);
	}
	else
	  strfcpy (path, p, sizeof (path));
	mutt_expand_path (path, sizeof (path));
	if ((body = mutt_make_file_attach (path)))
	{
	  body->description = safe_strdup (q);
	  for (parts = msg->content; parts->next; parts = parts->next) ;
	  parts->next = body;
	}
	else
	{
	  mutt_pretty_mailbox (path);
	  mutt_error (_("%s: unable to attach file. try again"), path);
	}
      }
      keep = 0;
    }



#ifdef HAVE_PGP
    else if (mutt_strncasecmp ("pgp:", cur->data, 4) == 0)
    {
      msg->pgp = mutt_parse_pgp_hdr (cur->data + 4, 0);
      keep = 0;
    }
#endif


    if (keep)
    {
      last = cur;
      cur = cur->next;
    }
    else
    {
      if (last)
	last->next = cur->next;
      else
	msg->env->userhdrs = cur->next;
      tmp = cur;
      cur = cur->next;
      tmp->next = NULL;
      mutt_free_list (&tmp);
    }
  }

  if (!in_reply_to)
    mutt_free_list (&msg->env->references);
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
/* fetch message from POP server */
int pop_fetch_message(MESSAGE *msg, CONTEXT *ctx, int msgno)
{
    int ret;
    void *uidl;
    char buf[LONG_STRING];
    char path[_POSIX_PATH_MAX];
    progress_t progressbar;
    POP_DATA *pop_data = (POP_DATA *)ctx->data;
    POP_CACHE *cache;
    HEADER *h = ctx->hdrs[msgno];
    unsigned short bcache = 1;

    /* see if we already have the message in body cache */
    if ((msg->fp = mutt_bcache_get(pop_data->bcache, h->data)))
        return 0;

    /*
     * see if we already have the message in our cache in
     * case $message_cachedir is unset
     */
    cache = &pop_data->cache[h->index % POP_CACHE_LEN];

    if (cache->path) {
        if (cache->index == h->index) {
            /* yes, so just return a pointer to the message */
            msg->fp = fopen(cache->path, "r");

            if (msg->fp)
                return 0;

            mutt_perror(cache->path);
            mutt_sleep(2);
            return -1;
        } else {
            /* clear the previous entry */
            unlink(cache->path);
            safe_free(&cache->path);
        }
    }

    FOREVER
    {
        if (pop_reconnect(ctx) < 0)
            return -1;

        /* verify that massage index is correct */
        if (h->refno < 0) {
            mutt_error _(
                "The message index is incorrect. Try reopening the mailbox.");
            mutt_sleep(2);
            return -1;
        }

        mutt_progress_init(&progressbar, _(
                               "Fetching message..."),
                           M_PROGRESS_SIZE, NetInc,
                           h->content->length + h->content->offset - 1);

        /* see if we can put in body cache; use our cache as fallback */
        if (!(msg->fp = mutt_bcache_put(pop_data->bcache, h->data, 1))) {
            /* no */
            bcache = 0;
            mutt_mktemp(path, sizeof(path));

            if (!(msg->fp = safe_fopen(path, "w+"))) {
                mutt_perror(path);
                mutt_sleep(2);
                return -1;
            }
        }

        snprintf(buf, sizeof(buf), "RETR %d\r\n", h->refno);

        ret =
            pop_fetch_data(pop_data, buf, &progressbar, fetch_message, msg->fp);

        if (ret == 0)
            break;

        safe_fclose(&msg->fp);

        /* if RETR failed (e.g. connection closed), be sure to remove either
         * the file in bcache or from POP's own cache since the next iteration
         * of the loop will re-attempt to put() the message */
        if (!bcache)
            unlink(path);

        if (ret == -2) {
            mutt_error("%s", pop_data->err_msg);
            mutt_sleep(2);
            return -1;
        }

        if (ret == -3) {
            mutt_error _("Can't write message to temporary file!");
            mutt_sleep(2);
            return -1;
        }
    }

    /* Update the header information.  Previously, we only downloaded a
     * portion of the headers, those required for the main display.
     */
    if (bcache)
        mutt_bcache_commit(pop_data->bcache, h->data);
    else {
        cache->index = h->index;
        cache->path = safe_strdup(path);
    }
    rewind(msg->fp);
    uidl = h->data;

    /* we replace envelop, key in subj_hash has to be updated as well */
    if (ctx->subj_hash
        && h->env->real_subj)
        hash_delete(ctx->subj_hash, h->env->real_subj, h, NULL);
    mutt_free_envelope(&h->env);
    h->env = mutt_read_rfc822_header(msg->fp, h, 0, 0);

    if (ctx->subj_hash
        && h->env->real_subj)
        hash_insert(ctx->subj_hash, h->env->real_subj, h, 1);

    h->data = uidl;
    h->lines = 0;
    fgets(buf, sizeof(buf), msg->fp);

    while (!feof(msg->fp)) {
        ctx->hdrs[msgno]->lines++;
        fgets(buf, sizeof(buf), msg->fp);
    }

    h->content->length = ftello(msg->fp) - h->content->offset;

    /* This needs to be done in case this is a multipart message */
    if (!WithCrypto)
        h->security = crypt_query(h->content);

    mutt_clear_error();
    rewind(msg->fp);

    return 0;
}