/* returns 1 if Mutt can't display this type of data, 0 otherwise */ int mutt_needs_mailcap (BODY * m) { switch (m->type) { case TYPETEXT: if (!ascii_strcasecmp ("plain", m->subtype) || !ascii_strcasecmp ("rfc822-headers", m->subtype) || !ascii_strcasecmp ("enriched", m->subtype)) return 0; break; case TYPEAPPLICATION: if ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp (m)) return 0; if ((WithCrypto & APPLICATION_SMIME) && mutt_is_application_smime (m)) return 0; break; case TYPEMULTIPART: case TYPEMESSAGE: return 0; } return 1; }
/** * crypt_query - Check out the type of encryption used * @param m Body of email * @retval num Flags, see #SecurityFlags * @retval 0 Error (#SEC_NO_FLAGS) * * Set the cached status values if there are any. */ SecurityFlags crypt_query(struct Body *m) { if (!WithCrypto || !m) return SEC_NO_FLAGS; SecurityFlags rc = SEC_NO_FLAGS; if (m->type == TYPE_APPLICATION) { if (WithCrypto & APPLICATION_PGP) rc |= mutt_is_application_pgp(m); if (WithCrypto & APPLICATION_SMIME) { rc |= mutt_is_application_smime(m); if (rc && m->goodsig) rc |= SEC_GOODSIGN; if (rc && m->badsig) rc |= SEC_BADSIGN; } } else if (((WithCrypto & APPLICATION_PGP) != 0) && (m->type == TYPE_TEXT)) { rc |= mutt_is_application_pgp(m); if (rc && m->goodsig) rc |= SEC_GOODSIGN; } if (m->type == TYPE_MULTIPART) { rc |= mutt_is_multipart_encrypted(m); rc |= mutt_is_multipart_signed(m); rc |= mutt_is_malformed_multipart_pgp_encrypted(m); if (rc && m->goodsig) rc |= SEC_GOODSIGN; } if ((m->type == TYPE_MULTIPART) || (m->type == TYPE_MESSAGE)) { SecurityFlags u = m->parts ? SEC_ALL_FLAGS : 0; /* Bits set in all parts */ SecurityFlags w = SEC_NO_FLAGS; /* Bits set in any part */ for (struct Body *b = m->parts; b; b = b->next) { const SecurityFlags v = crypt_query(b); u &= v; w |= v; } rc |= u | (w & ~SEC_GOODSIGN); if ((w & SEC_GOODSIGN) && !(u & SEC_GOODSIGN)) rc |= SEC_PARTSIGN; } return rc; }
static void set_copy_flags (HEADER *hdr, int decode, int decrypt, int *cmflags, int *chflags) { *cmflags = 0; *chflags = CH_UPDATE_LEN; if (WithCrypto && !decode && decrypt && (hdr->security & ENCRYPT)) { if ((WithCrypto & APPLICATION_PGP) && mutt_is_multipart_encrypted(hdr->content)) { *chflags = CH_NONEWLINE | CH_XMIT | CH_MIME; *cmflags = M_CM_DECODE_PGP; } else if ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp (hdr->content) & ENCRYPT) decode = 1; else if ((WithCrypto & APPLICATION_SMIME) && mutt_is_application_smime(hdr->content) & ENCRYPT) { *chflags = CH_NONEWLINE | CH_XMIT | CH_MIME; *cmflags = M_CM_DECODE_SMIME; } } if (decode) { *chflags = CH_XMIT | CH_MIME | CH_TXTPLAIN; *cmflags = M_CM_DECODE | M_CM_CHARCONV; if (!decrypt) /* If decode doesn't kick in for decrypt, */ { *chflags |= CH_DECODE; /* then decode RFC 2047 headers, */ if (option (OPTWEED)) { *chflags |= CH_WEED; /* and respect $weed. */ *cmflags |= M_CM_WEED; } } } }
/* args: * fp If not NULL, file containing the template * ctx If fp is NULL, the context containing the header with the template * newhdr The template is read into this HEADER * hdr The message to recall/resend * resend Set if resending (as opposed to recalling a postponed msg). * Resent messages enable header weeding, and also * discard any existing Message-ID and Mail-Followup-To. */ int mutt_prepare_template (FILE *fp, CONTEXT *ctx, HEADER *newhdr, HEADER *hdr, short resend) { MESSAGE *msg = NULL; char file[_POSIX_PATH_MAX]; BODY *b; FILE *bfp; int rv = -1; STATE s; int sec_type; 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; /* enable header weeding for resent messages */ newhdr->env = mutt_read_rfc822_header (fp, newhdr, 1, resend); newhdr->content->length = hdr->content->length; mutt_parse_part (fp, newhdr->content); /* If resending a message, don't keep message_id or mail_followup_to. * Otherwise, we are resuming a postponed message, and want to keep those * headers if they exist. */ if (resend) { FREE (&newhdr->env->message_id); FREE (&newhdr->env->mail_followup_to); } /* decrypt pgp/mime encoded messages */ if ((WithCrypto & APPLICATION_PGP) && (sec_type = mutt_is_multipart_encrypted (newhdr->content))) { newhdr->security |= sec_type; if (!crypt_valid_passphrase (sec_type)) goto err; mutt_message _("Decrypting message..."); if ((crypt_pgp_decrypt_mime (fp, &bfp, newhdr->content, &b) == -1) || b == NULL) { err: mx_close_message (ctx, &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 |= MUTT_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) && ((sec_type = mutt_is_application_pgp (b)) & (ENCRYPT|SIGN))) { mutt_body_handler (b, &s); newhdr->security |= sec_type; b->type = TYPETEXT; mutt_str_replace (&b->subtype, "plain"); mutt_delete_parameter ("x-action", &b->parameter); } else if ((WithCrypto & APPLICATION_SMIME) && ((sec_type = mutt_is_application_smime (b)) & (ENCRYPT|SIGN))) { mutt_body_handler (b, &s); newhdr->security |= sec_type; b->type = TYPETEXT; mutt_str_replace (&b->subtype, "plain"); } 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 (ctx, &msg); if (rv == -1) { mutt_free_envelope (&newhdr->env); mutt_free_body (&newhdr->content); } return rv; }