📄 handler.c
字号:
{ choice = b; type = TXTHTML; } } b = b->next; } } /* Finally, look for other possibilities */ if (!choice) { if (a && a->parts) b = a->parts; else b = a; while (b) { if (mutt_can_decode (b)) choice = b; b = b->next; } } if (choice) { if (s->flags & M_DISPLAY && !option (OPTWEED)) { fseeko (s->fpin, choice->hdr_offset, 0); mutt_copy_bytes(s->fpin, s->fpout, choice->offset-choice->hdr_offset); } mutt_body_handler (choice, s); } else if (s->flags & M_DISPLAY) { /* didn't find anything that we could display! */ state_mark_attach (s); state_puts(_("[-- Error: Could not display any parts of Multipart/Alternative! --]\n"), s); rc = -1; } if (mustfree) mutt_free_body(&a); return rc;}/* handles message/rfc822 body parts */int message_handler (BODY *a, STATE *s){ struct stat st; BODY *b; LOFF_T off_start; int rc = 0; off_start = ftello (s->fpin); if (a->encoding == ENCBASE64 || a->encoding == ENCQUOTEDPRINTABLE || a->encoding == ENCUUENCODED) { fstat (fileno (s->fpin), &st); b = mutt_new_body (); b->length = (LOFF_T) st.st_size; b->parts = mutt_parse_messageRFC822 (s->fpin, b); } else b = a; if (b->parts) { mutt_copy_hdr (s->fpin, s->fpout, off_start, b->parts->offset, (((s->flags & M_WEED) || ((s->flags & (M_DISPLAY|M_PRINTING)) && option (OPTWEED))) ? (CH_WEED | CH_REORDER) : 0) | (s->prefix ? CH_PREFIX : 0) | CH_DECODE | CH_FROM, s->prefix); if (s->prefix) state_puts (s->prefix, s); state_putc ('\n', s); rc = mutt_body_handler (b->parts, s); } if (a->encoding == ENCBASE64 || a->encoding == ENCQUOTEDPRINTABLE || a->encoding == ENCUUENCODED) mutt_free_body (&b); return rc;}/* returns 1 if decoding the attachment will produce output */int mutt_can_decode (BODY *a){ char type[STRING]; snprintf (type, sizeof (type), "%s/%s", TYPE (a), a->subtype); if (mutt_is_autoview (a, type)) return (rfc1524_mailcap_lookup (a, type, NULL, M_AUTOVIEW)); else if (a->type == TYPETEXT) return (1); else if (a->type == TYPEMESSAGE) return (1); else if (a->type == TYPEMULTIPART) { BODY *p; if (WithCrypto) { if (ascii_strcasecmp (a->subtype, "signed") == 0 || ascii_strcasecmp (a->subtype, "encrypted") == 0) return (1); } for (p = a->parts; p; p = p->next) { if (mutt_can_decode (p)) return (1); } } else if (WithCrypto && a->type == TYPEAPPLICATION) { if ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp(a)) return (1); if ((WithCrypto & APPLICATION_SMIME) && mutt_is_application_smime(a)) return (1); } return (0);}int multipart_handler (BODY *a, STATE *s){ BODY *b, *p; char length[5]; struct stat st; int count; int rc = 0; if (a->encoding == ENCBASE64 || a->encoding == ENCQUOTEDPRINTABLE || a->encoding == ENCUUENCODED) { fstat (fileno (s->fpin), &st); b = mutt_new_body (); b->length = (long) st.st_size; b->parts = mutt_parse_multipart (s->fpin, mutt_get_parameter ("boundary", a->parameter), (long) st.st_size, ascii_strcasecmp ("digest", a->subtype) == 0); } else b = a; for (p = b->parts, count = 1; p; p = p->next, count++) { if (s->flags & M_DISPLAY) { state_mark_attach (s); state_printf (s, _("[-- Attachment #%d"), count); if (p->description || p->filename || p->form_name) { state_puts (": ", s); state_puts (p->description ? p->description : p->filename ? p->filename : p->form_name, s); } state_puts (" --]\n", s); mutt_pretty_size (length, sizeof (length), p->length); state_mark_attach (s); state_printf (s, _("[-- Type: %s/%s, Encoding: %s, Size: %s --]\n"), TYPE (p), p->subtype, ENCODING (p->encoding), length); if (!option (OPTWEED)) { fseeko (s->fpin, p->hdr_offset, 0); mutt_copy_bytes(s->fpin, s->fpout, p->offset-p->hdr_offset); } else state_putc ('\n', s); } else { if (p->description && mutt_can_decode (p)) state_printf (s, "Content-Description: %s\n", p->description); if (p->form_name) state_printf(s, "%s: \n", p->form_name); } rc = mutt_body_handler (p, s); state_putc ('\n', s); if (rc || ((s->flags & M_REPLYING) && (option (OPTINCLUDEONLYFIRST)) && (s->flags & M_FIRSTDONE))) break; } if (a->encoding == ENCBASE64 || a->encoding == ENCQUOTEDPRINTABLE || a->encoding == ENCUUENCODED) mutt_free_body (&b); return rc;}int autoview_handler (BODY *a, STATE *s){ rfc1524_entry *entry = rfc1524_new_entry (); char buffer[LONG_STRING]; char type[STRING]; char command[LONG_STRING]; char tempfile[_POSIX_PATH_MAX] = ""; char *fname; FILE *fpin = NULL; FILE *fpout = NULL; FILE *fperr = NULL; int piped = FALSE; pid_t thepid; int rc = 0; snprintf (type, sizeof (type), "%s/%s", TYPE (a), a->subtype); rfc1524_mailcap_lookup (a, type, entry, M_AUTOVIEW); fname = safe_strdup (a->filename); mutt_sanitize_filename (fname, 1); rfc1524_expand_filename (entry->nametemplate, fname, tempfile, sizeof (tempfile)); FREE (&fname); if (entry->command) { strfcpy (command, entry->command, sizeof (command)); /* rfc1524_expand_command returns 0 if the file is required */ piped = rfc1524_expand_command (a, tempfile, type, command, sizeof (command)); if (s->flags & M_DISPLAY) { state_mark_attach (s); state_printf (s, _("[-- Autoview using %s --]\n"), command); mutt_message(_("Invoking autoview command: %s"),command); } if ((fpin = safe_fopen (tempfile, "w+")) == NULL) { mutt_perror ("fopen"); rfc1524_free_entry (&entry); return -1; } mutt_copy_bytes (s->fpin, fpin, a->length); if(!piped) { safe_fclose (&fpin); thepid = mutt_create_filter (command, NULL, &fpout, &fperr); } else { unlink (tempfile); fflush (fpin); rewind (fpin); thepid = mutt_create_filter_fd (command, NULL, &fpout, &fperr, fileno(fpin), -1, -1); } if (thepid < 0) { mutt_perror _("Can't create filter"); if (s->flags & M_DISPLAY) { state_mark_attach (s); state_printf (s, _("[-- Can't run %s. --]\n"), command); } rc = -1; goto bail; } if (s->prefix) { while (fgets (buffer, sizeof(buffer), fpout) != NULL) { state_puts (s->prefix, s); state_puts (buffer, s); } /* check for data on stderr */ if (fgets (buffer, sizeof(buffer), fperr)) { if (s->flags & M_DISPLAY) { state_mark_attach (s); state_printf (s, _("[-- Autoview stderr of %s --]\n"), command); } state_puts (s->prefix, s); state_puts (buffer, s); while (fgets (buffer, sizeof(buffer), fperr) != NULL) { state_puts (s->prefix, s); state_puts (buffer, s); } } } else { mutt_copy_stream (fpout, s->fpout); /* Check for stderr messages */ if (fgets (buffer, sizeof(buffer), fperr)) { if (s->flags & M_DISPLAY) { state_mark_attach (s); state_printf (s, _("[-- Autoview stderr of %s --]\n"), command); } state_puts (buffer, s); mutt_copy_stream (fperr, s->fpout); } } bail: safe_fclose (&fpout); safe_fclose (&fperr); mutt_wait_filter (thepid); if (piped) safe_fclose (&fpin); else mutt_unlink (tempfile); if (s->flags & M_DISPLAY) mutt_clear_error (); } rfc1524_free_entry (&entry); return rc;}static int external_body_handler (BODY *b, STATE *s){ const char *access_type; const char *expiration; time_t expire; access_type = mutt_get_parameter ("access-type", b->parameter); if (!access_type) { if (s->flags & M_DISPLAY) { state_mark_attach (s); state_puts (_("[-- Error: message/external-body has no access-type parameter --]\n"), s); } return -1; } expiration = mutt_get_parameter ("expiration", b->parameter); if (expiration) expire = mutt_parse_date (expiration, NULL); else expire = -1; if (!ascii_strcasecmp (access_type, "x-mutt-deleted")) { if (s->flags & (M_DISPLAY|M_PRINTING)) { char *length; char pretty_size[10]; state_mark_attach (s); state_printf (s, _("[-- This %s/%s attachment "), TYPE(b->parts), b->parts->subtype); length = mutt_get_parameter ("length", b->parameter); if (length) { mutt_pretty_size (pretty_size, sizeof (pretty_size), strtol (length, NULL, 10)); state_printf (s, _("(size %s bytes) "), pretty_size); } state_puts (_("has been deleted --]\n"), s); if (expire != -1) { state_mark_attach (s); state_printf (s, _("[-- on %s --]\n"), expiration); } if (b->parts->filename) { state_mark_attach (s); state_printf (s, _("[-- name: %s --]\n"), b->parts->filename); } mutt_copy_hdr (s->fpin, s->fpout, ftello (s->fpin), b->parts->offset, (option (OPTWEED) ? (CH_WEED | CH_REORDER) : 0) | CH_DECODE , NULL); } } else if(expiration && expire < time(NULL)) { if (s->flags & M_DISPLAY) { state_mark_attach (s); state_printf (s, _("[-- This %s/%s attachment is not included, --]\n"), TYPE(b->parts), b->parts->subtype); state_attach_puts (_("[-- and the indicated external source has --]\n" "[-- expired. --]\n"), s); mutt_copy_hdr(s->fpin, s->fpout, ftello (s->fpin), b->parts->offset, (option (OPTWEED) ? (CH_WEED | CH_REORDER) : 0) | CH_DECODE, NULL); } } else { if (s->flags & M_DISPLAY) { state_mark_attach (s); state_printf (s, _("[-- This %s/%s attachment is not included, --]\n"), TYPE (b->parts), b->parts->subtype); state_mark_attach (s); state_printf (s, _("[-- and the indicated access-type %s is unsupported --]\n"), access_type); mutt_copy_hdr (s->fpin, s->fpout, ftello (s->fpin), b->parts->offset, (option (OPTWEED) ? (CH_WEED | CH_REORDER) : 0) | CH_DECODE , NULL); } } return 0;}void mutt_decode_attachment (BODY *b, STATE *s){ int istext = mutt_is_text_part (b); iconv_t cd = (iconv_t)(-1); if (istext && s->flags & M_CHARCONV) { char *charset = mutt_get_parameter ("charset", b->parameter); if (charset && Charset) cd = mutt_iconv_open (Charset, charset, M_ICONV_HOOK_FROM); } fseeko (s->fpin, b->offset, 0); switch (b->encoding) { case ENCQUOTEDPRINTABLE: mutt_decode_quoted (s, b->length, istext || ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp (b)), cd); break; case ENCBASE64: mutt_decode_base64 (s, b->length, istext || ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp (b)), cd); break; case ENCUUENCODED: mutt_decode_uuencoded (s, b->length, istext || ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp (b)), cd); break; default: mutt_decode_xbit (s, b->length, istext || ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp (b)), cd); break; } if (cd != (iconv_t)(-1)) iconv_close (cd);}int mutt_body_handler (BODY *b, STATE *s){ int decode = 0; int plaintext = 0; FILE *fp = NULL; char tempfile[_POSIX_PATH_MAX]; handler_t handler = NULL; long tmpoffset = 0; size_t tmplength = 0; char type[STRING]; int rc = 0; int oflags = s->flags; /* first determine which handler to use to process this part */ snprintf (type, sizeof (type), "%s/%s", TYPE (b), b->subtype); if (mutt_is_autoview (b, type)) { rfc1524_entry *entry = rfc1524_new_entry (); if (rfc1524_mailcap_lookup (b, type, entry, M_AUTOVIEW)) { handler = autoview_handler; s->flags &= ~M_CHARCONV; } rfc1524_free_entry (&entry); } else if (b->type == TYPETEXT) { if (ascii_strcasecmp ("plain", b->subtype) == 0) { /* avoid copying this part twice since removing the transfer-encoding is * the only operation needed. */ if ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp (b)) handler = crypt_pgp_application_pgp_handler; else if (ascii_strcasecmp ("flowed", mutt_get_parameter ("format", b->parameter)) == 0) handler = text_plain_flowed_handler; else plaintext = 1; } else if (ascii_strcasecmp ("enriched", b->subtype) == 0) handler = text_enriched_handler; else /* text body type without a handler */ plaintext = 1; } else if (b->type == TYPEMESSAGE) { if(mutt_is_message_type(b->type, b->subtype)) handler = message_handler; else if (!ascii_strcasecmp ("delivery-status", b->subtype)) plaintext = 1; else if (!ascii_strcasecmp ("external-body", b->subtype)) handler = external_body_handler; } else if (b->type == TYPEMULTIPART) { char *p; if (ascii_strcasecmp ("alternative", b->subtype) == 0) handler = alternative_handler; else if (WithCrypto && ascii_strcasecmp ("signed", b->subtype) == 0) { p = mutt_get_parameter ("protocol", b->parameter); if (!p) mutt_error _("Error: multipart/signed has no protocol."); else if (s->flags & M_VERIFY) handler = mutt_signed_handler; } else if ((WithCrypto & APPLICATION_PGP) && ascii_strcasecmp ("encrypted", b->subtype) == 0) { p = mutt_get_parameter ("protocol", b->parameter); if (!p) mutt_error _("Error: multipart/encrypted has no protocol parameter!"); else if (ascii_strcasecmp ("application/pgp-encrypted", p) == 0) handler = crypt_pgp_encrypted_handler; } if (!handler) handler = multipart_handler; } else if (WithCrypto && b->type == TYPEAPPLICATION) { if ((WithCrypto & APPLICATION_PGP) && mutt_is_application_pgp (b)) handler = crypt_pgp_application_pgp_handler; if ((WithCrypto & APPLICATION_SMIME) && mutt_is_application_smime(b)) handler = crypt_smime_application_smime_handler; } if (plaintext || handler) { fseeko (s->fpin, b->offset, 0); /* see if we need to decode this part before processing it */ if (b->encoding == ENCBASE64 || b->encoding == ENCQUOTEDPRINTABLE || b->encoding == ENCUUENCODED || plaintext || mutt_is_text_part (b)) /* text subtypes may * require character * set conversion even * with 8bit encoding. */ { int origType = b->type; char *savePrefix = NULL; if (!plaintext) { /* decode to a tempfile, saving the original destination */ fp = s->fpout; mutt_mktemp (tempfile); if ((s->fpout = safe_fopen (tempfile, "w")) == NULL) { mutt_error _("Unable to open temporary file!"); goto bail; } /* decoding the attachment changes the size and offset, so save a copy * of the "real" values now, and restore them after processing */ tmplength = b->length; tmpoffset = b->offset; /* if we are decoding binary bodies, we don't want to prefix each * line with the prefix or else the data will get corrupted. */ savePrefix = s->prefix; s->prefix = NULL; decode = 1; } else b->type = TYPETEXT; mutt_decode_attachment (b, s); if (decode) { b->length = ftello (s->fpout); b->offset = 0; fclose (s->fpout); /* restore final destination and substitute the tempfile for input */ s->fpout = fp; fp = s->fpin; s->fpin = fopen (tempfile, "r"); unlink (tempfile); /* restore the prefix */ s->prefix = savePrefix; } b->type = origType; } /* process the (decoded) body part */ if (handler) { rc = handler (b, s); if (decode) { b->length = tmplength; b->offset = tmpoffset; /* restore the original source stream */ fclose (s->fpin); s->fpin = fp; } } s->flags |= M_FIRSTDONE; } else if (s->flags & M_DISPLAY) { state_mark_attach (s); state_printf (s, _("[-- %s/%s is unsupported "), TYPE (b), b->subtype); if (!option (OPTVIEWATTACH)) { if (km_expand_key (type, sizeof(type), km_find_func (MENU_PAGER, OP_VIEW_ATTACHMENTS))) fprintf (s->fpout, _("(use '%s' to view this part)"), type); else fputs (_("(need 'view-attachments' bound to key!)"), s->fpout); } fputs (" --]\n", s->fpout); } bail: s->flags = oflags | (s->flags & M_FIRSTDONE); return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -