NeoMutt  2022-04-29-249-gaae397
Teaching an old dog new tricks
DOXYGEN
Mime Handler API

Prototype for a function to handle MIME parts. More...

Functions

int text_enriched_handler (struct Body *a, struct State *s)
 Handler for enriched text - Implements handler_t -. More...
 
static int autoview_handler (struct Body *a, struct State *s)
 Handler for autoviewable attachments - Implements handler_t -. More...
 
static int text_plain_handler (struct Body *b, struct State *s)
 Handler for plain text - Implements handler_t -. More...
 
static int message_handler (struct Body *a, struct State *s)
 Handler for message/rfc822 body parts - Implements handler_t -. More...
 
static int external_body_handler (struct Body *b, struct State *s)
 Handler for external-body emails - Implements handler_t -. More...
 
static int alternative_handler (struct Body *a, struct State *s)
 Handler for multipart alternative emails - Implements handler_t -. More...
 
static int multilingual_handler (struct Body *a, struct State *s)
 Handler for multi-lingual emails - Implements handler_t -. More...
 
static int multipart_handler (struct Body *a, struct State *s)
 Handler for multipart emails - Implements handler_t -. More...
 
static int valid_pgp_encrypted_handler (struct Body *b, struct State *s)
 Handler for valid pgp-encrypted emails - Implements handler_t -. More...
 
static int malformed_pgp_encrypted_handler (struct Body *b, struct State *s)
 Handler for invalid pgp-encrypted emails - Implements handler_t -. More...
 
int mutt_protected_headers_handler (struct Body *b, struct State *s)
 Process a protected header - Implements handler_t -. More...
 
int mutt_signed_handler (struct Body *b, struct State *s)
 Verify a "multipart/signed" body - Implements handler_t -. More...
 
int crypt_pgp_application_handler (struct Body *b, struct State *s)
 Wrapper for CryptModuleSpecs::application_handler() - Implements handler_t -. More...
 
int crypt_pgp_encrypted_handler (struct Body *b, struct State *s)
 Wrapper for CryptModuleSpecs::encrypted_handler() - Implements handler_t -. More...
 
int crypt_smime_application_handler (struct Body *b, struct State *s)
 Wrapper for CryptModuleSpecs::application_handler() - Implements handler_t -. More...
 
int rfc3676_handler (struct Body *a, struct State *s)
 Body handler implementing RFC3676 for format=flowed - Implements handler_t -. More...
 

Detailed Description

Prototype for a function to handle MIME parts.

Parameters
bBody of the email
sState of text being processed
Return values
0Success
-1Error

Function Documentation

◆ text_enriched_handler()

int text_enriched_handler ( struct Body a,
struct State s 
)

Handler for enriched text - Implements handler_t -.

Return values
0Always

Definition at line 459 of file enriched.c.

460{
461 enum
462 {
463 TEXT,
464 LANGLE,
465 TAG,
466 BOGUS_TAG,
467 NEWLINE,
468 ST_EOF,
469 DONE
470 } state = TEXT;
471
472 long bytes = a->length;
473 struct EnrichedState stte = { 0 };
474 wint_t wc = 0;
475 int tag_len = 0;
476 wchar_t tag[1024 + 1];
477
478 stte.s = s;
479 stte.wrap_margin = ((s->wraplen > 4) && ((s->flags & MUTT_DISPLAY) || (s->wraplen < 76))) ?
480 s->wraplen - 4 :
481 72;
482 stte.line_max = stte.wrap_margin * 4;
483 stte.line = mutt_mem_calloc((stte.line_max + 1), sizeof(wchar_t));
484 stte.param = mutt_mem_calloc(256, sizeof(wchar_t));
485
486 stte.param_len = 256;
487 stte.param_used = 0;
488
489 if (s->prefix)
490 {
491 state_puts(s, s->prefix);
493 }
494
495 while (state != DONE)
496 {
497 if (state != ST_EOF)
498 {
499 if (!bytes || ((wc = fgetwc(s->fp_in)) == WEOF))
500 state = ST_EOF;
501 else
502 bytes--;
503 }
504
505 switch (state)
506 {
507 case TEXT:
508 switch (wc)
509 {
510 case '<':
511 state = LANGLE;
512 break;
513
514 case '\n':
515 if (stte.tag_level[RICH_NOFILL])
516 {
517 enriched_flush(&stte, true);
518 }
519 else
520 {
521 enriched_putwc((wchar_t) ' ', &stte);
522 state = NEWLINE;
523 }
524 break;
525
526 default:
527 enriched_putwc(wc, &stte);
528 }
529 break;
530
531 case LANGLE:
532 if (wc == (wchar_t) '<')
533 {
534 enriched_putwc(wc, &stte);
535 state = TEXT;
536 break;
537 }
538 else
539 {
540 tag_len = 0;
541 state = TAG;
542 }
543 /* Yes, (it wasn't a <<, so this char is first in TAG) */
544 /* fallthrough */
545 case TAG:
546 if (wc == (wchar_t) '>')
547 {
548 tag[tag_len] = (wchar_t) '\0';
549 enriched_set_flags(tag, &stte);
550 state = TEXT;
551 }
552 else if (tag_len < 1024) /* ignore overly long tags */
553 tag[tag_len++] = wc;
554 else
555 state = BOGUS_TAG;
556 break;
557
558 case BOGUS_TAG:
559 if (wc == (wchar_t) '>')
560 state = TEXT;
561 break;
562
563 case NEWLINE:
564 if (wc == (wchar_t) '\n')
565 enriched_flush(&stte, true);
566 else
567 {
568 ungetwc(wc, s->fp_in);
569 bytes++;
570 state = TEXT;
571 }
572 break;
573
574 case ST_EOF:
575 enriched_putwc((wchar_t) '\0', &stte);
576 enriched_flush(&stte, true);
577 state = DONE;
578 break;
579
580 default:
581 /* not reached */
582 break;
583 }
584 }
585
586 state_putc(s, '\n'); /* add a final newline */
587
588 FREE(&(stte.buffer));
589 FREE(&(stte.line));
590 FREE(&(stte.param));
591
592 return 0;
593}
@ RICH_NOFILL
Text will not be reformatted.
Definition: enriched.c:54
static void enriched_flush(struct EnrichedState *stte, bool wrap)
Write enriched text to the State.
Definition: enriched.c:235
static void enriched_putwc(wchar_t c, struct EnrichedState *stte)
Write one wide character to the state.
Definition: enriched.c:271
static void enriched_set_flags(const wchar_t *tag, struct EnrichedState *stte)
Set flags on the enriched text state.
Definition: enriched.c:370
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:43
#define state_puts(STATE, STR)
Definition: state.h:56
#define state_putc(STATE, STR)
Definition: state.h:57
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
State of enriched-text parser.
Definition: enriched.c:98
wchar_t * buffer
Definition: enriched.c:99
size_t param_used
Definition: enriched.c:109
wchar_t * param
Definition: enriched.c:101
wchar_t * line
Definition: enriched.c:100
int tag_level[RICH_MAX]
Definition: enriched.c:111
struct State * s
Definition: enriched.c:113
size_t param_len
Definition: enriched.c:110
size_t line_max
Definition: enriched.c:105
int wrap_margin
Definition: enriched.c:112
size_t indent_len
Definition: enriched.c:106
int wraplen
Width to wrap lines to (when flags & MUTT_DISPLAY)
Definition: state.h:51
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:50
char * prefix
String to add to the beginning of each output line.
Definition: state.h:49
FILE * fp_in
File to read from.
Definition: state.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ autoview_handler()

static int autoview_handler ( struct Body a,
struct State s 
)
static

Handler for autoviewable attachments - Implements handler_t -.

Definition at line 524 of file handler.c.

525{
526 struct MailcapEntry *entry = mailcap_entry_new();
527 char buf[1024] = { 0 };
528 char type[256] = { 0 };
529 struct Buffer *cmd = mutt_buffer_pool_get();
530 struct Buffer *tempfile = mutt_buffer_pool_get();
531 char *fname = NULL;
532 FILE *fp_in = NULL;
533 FILE *fp_out = NULL;
534 FILE *fp_err = NULL;
535 pid_t pid;
536 int rc = 0;
537
538 snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
539 mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_AUTOVIEW);
540
541 fname = mutt_str_dup(a->filename);
542 mutt_file_sanitize_filename(fname, true);
543 mailcap_expand_filename(entry->nametemplate, fname, tempfile);
544 FREE(&fname);
545
546 if (entry->command)
547 {
548 mutt_buffer_strcpy(cmd, entry->command);
549
550 /* mailcap_expand_command returns 0 if the file is required */
551 bool piped = mailcap_expand_command(a, mutt_buffer_string(tempfile), type, cmd);
552
553 if (s->flags & MUTT_DISPLAY)
554 {
556 state_printf(s, _("[-- Autoview using %s --]\n"), mutt_buffer_string(cmd));
557 mutt_message(_("Invoking autoview command: %s"), mutt_buffer_string(cmd));
558 }
559
560 fp_in = mutt_file_fopen(mutt_buffer_string(tempfile), "w+");
561 if (!fp_in)
562 {
563 mutt_perror("fopen");
564 mailcap_entry_free(&entry);
565 rc = -1;
566 goto cleanup;
567 }
568
569 mutt_file_copy_bytes(s->fp_in, fp_in, a->length);
570
571 if (piped)
572 {
573 unlink(mutt_buffer_string(tempfile));
574 fflush(fp_in);
575 rewind(fp_in);
576 pid = filter_create_fd(mutt_buffer_string(cmd), NULL, &fp_out, &fp_err,
577 fileno(fp_in), -1, -1);
578 }
579 else
580 {
581 mutt_file_fclose(&fp_in);
582 pid = filter_create(mutt_buffer_string(cmd), NULL, &fp_out, &fp_err);
583 }
584
585 if (pid < 0)
586 {
587 mutt_perror(_("Can't create filter"));
588 if (s->flags & MUTT_DISPLAY)
589 {
591 state_printf(s, _("[-- Can't run %s. --]\n"), mutt_buffer_string(cmd));
592 }
593 rc = -1;
594 goto bail;
595 }
596
597 if (s->prefix)
598 {
599 /* Remove ansi and formatting from autoview output in replies only. The
600 * user may want to see the formatting in the pager, but it shouldn't be
601 * in their quoted reply text too. */
602 struct Buffer *stripped = mutt_buffer_pool_get();
603 while (fgets(buf, sizeof(buf), fp_out))
604 {
605 mutt_buffer_strip_formatting(stripped, buf, false);
606 state_puts(s, s->prefix);
607 state_puts(s, mutt_buffer_string(stripped));
608 }
609 mutt_buffer_pool_release(&stripped);
610
611 /* check for data on stderr */
612 if (fgets(buf, sizeof(buf), fp_err))
613 {
614 if (s->flags & MUTT_DISPLAY)
615 {
617 state_printf(s, _("[-- Autoview stderr of %s --]\n"), mutt_buffer_string(cmd));
618 }
619
620 state_puts(s, s->prefix);
621 state_puts(s, buf);
622 while (fgets(buf, sizeof(buf), fp_err))
623 {
624 state_puts(s, s->prefix);
625 state_puts(s, buf);
626 }
627 }
628 }
629 else
630 {
631 mutt_file_copy_stream(fp_out, s->fp_out);
632 /* Check for stderr messages */
633 if (fgets(buf, sizeof(buf), fp_err))
634 {
635 if (s->flags & MUTT_DISPLAY)
636 {
638 state_printf(s, _("[-- Autoview stderr of %s --]\n"), mutt_buffer_string(cmd));
639 }
640
641 state_puts(s, buf);
642 mutt_file_copy_stream(fp_err, s->fp_out);
643 }
644 }
645
646 bail:
647 mutt_file_fclose(&fp_out);
648 mutt_file_fclose(&fp_err);
649
650 filter_wait(pid);
651 if (piped)
652 mutt_file_fclose(&fp_in);
653 else
655
656 if (s->flags & MUTT_DISPLAY)
658 }
659
660cleanup:
661 mailcap_entry_free(&entry);
662
664 mutt_buffer_pool_release(&tempfile);
665
666 return rc;
667}
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:327
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
void mutt_buffer_strip_formatting(struct Buffer *dest, const char *src, bool strip_markers)
Removes ANSI and backspace formatting.
Definition: display.c:674
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:260
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
int mutt_file_copy_bytes(FILE *fp_in, FILE *fp_out, size_t size)
Copy some content from one file to another.
Definition: file.c:230
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:647
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:194
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr)
Run a command on a pipe (optionally connect stdin/stdout)
Definition: filter.c:61
#define mutt_message(...)
Definition: logging.h:86
#define mutt_perror(...)
Definition: logging.h:88
bool mailcap_lookup(struct Body *a, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: mailcap.c:473
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:444
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:435
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:67
void mailcap_expand_filename(const char *nametemplate, const char *oldfile, struct Buffer *newfile)
Expand a new filename from a template or existing filename.
Definition: mailcap.c:542
@ MUTT_MC_AUTOVIEW
Mailcap autoview field.
Definition: mailcap.h:60
#define TYPE(body)
Definition: mime.h:89
#define _(a)
Definition: message.h:28
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:183
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:71
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
char * subtype
content-type subtype
Definition: body.h:60
char * filename
When sending a message, this is the file to which this structure refers.
Definition: body.h:58
String manipulation buffer.
Definition: buffer.h:34
A mailcap entry.
Definition: mailcap.h:36
char * nametemplate
Definition: mailcap.h:43
char * command
Definition: mailcap.h:37
FILE * fp_out
File to write to.
Definition: state.h:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ text_plain_handler()

static int text_plain_handler ( struct Body b,
struct State s 
)
static

Handler for plain text - Implements handler_t -.

Return values
0Always

When generating format=flowed ($text_flowed is set) from format=fixed, strip all trailing spaces to improve interoperability; if $text_flowed is unset, simply verbatim copy input.

Definition at line 677 of file handler.c.

678{
679 char *buf = NULL;
680 size_t sz = 0;
681
682 while ((buf = mutt_file_read_line(buf, &sz, s->fp_in, NULL, MUTT_RL_NO_FLAGS)))
683 {
684 const bool c_text_flowed = cs_subset_bool(NeoMutt->sub, "text_flowed");
685 if (!mutt_str_equal(buf, "-- ") && c_text_flowed)
686 {
687 size_t len = mutt_str_len(buf);
688 while ((len > 0) && (buf[len - 1] == ' '))
689 buf[--len] = '\0';
690 }
691 if (s->prefix)
692 state_puts(s, s->prefix);
693 state_puts(s, buf);
694 state_putc(s, '\n');
695 }
696
697 FREE(&buf);
698 return 0;
699}
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:720
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition: file.h:38
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ message_handler()

static int message_handler ( struct Body a,
struct State s 
)
static

Handler for message/rfc822 body parts - Implements handler_t -.

Definition at line 704 of file handler.c.

705{
706 struct Body *b = NULL;
707 LOFF_T off_start;
708 int rc = 0;
709
710 off_start = ftello(s->fp_in);
711 if (off_start < 0)
712 return -1;
713
714 if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
715 (a->encoding == ENC_UUENCODED))
716 {
717 b = mutt_body_new();
720 }
721 else
722 b = a;
723
724 if (b->parts)
725 {
727 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
728 if ((s->flags & MUTT_WEED) || ((s->flags & (MUTT_DISPLAY | MUTT_PRINTING)) && c_weed))
729 chflags |= CH_WEED | CH_REORDER;
730 if (s->prefix)
731 chflags |= CH_PREFIX;
732 if (s->flags & MUTT_DISPLAY)
733 chflags |= CH_DISPLAY;
734
735 mutt_copy_hdr(s->fp_in, s->fp_out, off_start, b->parts->offset, chflags, s->prefix, 0);
736
737 if (s->prefix)
738 state_puts(s, s->prefix);
739 state_putc(s, '\n');
740
741 rc = mutt_body_handler(b->parts, s);
742 }
743
744 if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
745 (a->encoding == ENC_UUENCODED))
746 {
747 mutt_body_free(&b);
748 }
749
750 return rc;
751}
int mutt_copy_hdr(FILE *fp_in, FILE *fp_out, LOFF_T off_start, LOFF_T off_end, CopyHeaderFlags chflags, const char *prefix, int wraplen)
Copy header from one file to another.
Definition: copy.c:104
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:54
#define CH_PREFIX
Quote header using $indent_string string?
Definition: copy.h:57
#define CH_FROM
Retain the "From " message separator?
Definition: copy.h:56
#define CH_WEED
Weed the headers?
Definition: copy.h:53
#define CH_REORDER
Re-order output of headers (specified by 'hdr_order')
Definition: copy.h:59
#define CH_DISPLAY
Display result to user.
Definition: copy.h:70
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:50
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
struct Body * mutt_body_new(void)
Create a new Body.
Definition: body.c:43
long mutt_file_get_size_fp(FILE *fp)
Get the size of a file.
Definition: file.c:1569
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1597
@ ENC_UUENCODED
UUEncoded text.
Definition: mime.h:54
@ ENC_BASE64
Base-64 encoded text.
Definition: mime.h:52
@ ENC_QUOTED_PRINTABLE
Quoted-printable text.
Definition: mime.h:51
#define MUTT_WEED
Weed headers even when not in display mode.
Definition: state.h:35
#define MUTT_PRINTING
Are we printing? - MUTT_DISPLAY "light".
Definition: state.h:37
struct Body * mutt_rfc822_parse_message(FILE *fp, struct Body *parent)
Parse a Message/RFC822 body.
Definition: parse.c:1751
The body of an email.
Definition: body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ external_body_handler()

static int external_body_handler ( struct Body b,
struct State s 
)
static

Handler for external-body emails - Implements handler_t -.

Definition at line 756 of file handler.c.

757{
758 const char *str = NULL;
759 char strbuf[1024] = { 0 };
760
761 const char *access_type = mutt_param_get(&b->parameter, "access-type");
762 if (!access_type)
763 {
764 if (s->flags & MUTT_DISPLAY)
765 {
767 state_puts(s, _("[-- Error: message/external-body has no access-type parameter --]\n"));
768 return 0;
769 }
770 else
771 return -1;
772 }
773
774 const char *expiration = mutt_param_get(&b->parameter, "expiration");
775 time_t expire;
776 if (expiration)
777 expire = mutt_date_parse_date(expiration, NULL);
778 else
779 expire = -1;
780
781 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
782 if (mutt_istr_equal(access_type, "x-mutt-deleted"))
783 {
784 if (s->flags & (MUTT_DISPLAY | MUTT_PRINTING))
785 {
786 char pretty_size[10] = { 0 };
787 char *length = mutt_param_get(&b->parameter, "length");
788 if (length)
789 {
790 long size = strtol(length, NULL, 10);
791 mutt_str_pretty_size(pretty_size, sizeof(pretty_size), size);
792 if (expire != -1)
793 {
794 str = ngettext(
795 /* L10N: If the translation of this string is a multi line string, then
796 each line should start with "[-- " and end with " --]".
797 The first "%s/%s" is a MIME type, e.g. "text/plain". The last %s
798 expands to a date as returned by `mutt_date_parse_date()`.
799
800 Note: The size argument printed is not the actual number as passed
801 to gettext but the prettified version, e.g. size = 2048 will be
802 printed as 2K. Your language might be sensitive to that: For
803 example although '1K' and '1024' represent the same number your
804 language might inflect the noun 'byte' differently.
805
806 Sadly, we can't do anything about that at the moment besides
807 passing the precise size in bytes. If you are interested the
808 function responsible for the prettification is
809 mutt_str_pretty_size() in mutt/string.c. */
810 "[-- This %s/%s attachment (size %s byte) has been deleted --]\n"
811 "[-- on %s --]\n",
812 "[-- This %s/%s attachment (size %s bytes) has been deleted --]\n"
813 "[-- on %s --]\n",
814 size);
815 }
816 else
817 {
818 str = ngettext(
819 /* L10N: If the translation of this string is a multi line string, then
820 each line should start with "[-- " and end with " --]".
821 The first "%s/%s" is a MIME type, e.g. "text/plain".
822
823 Note: The size argument printed is not the actual number as passed
824 to gettext but the prettified version, e.g. size = 2048 will be
825 printed as 2K. Your language might be sensitive to that: For
826 example although '1K' and '1024' represent the same number your
827 language might inflect the noun 'byte' differently.
828
829 Sadly, we can't do anything about that at the moment besides
830 passing the precise size in bytes. If you are interested the
831 function responsible for the prettification is
832 mutt_str_pretty_size() in mutt/string.c. */
833 "[-- This %s/%s attachment (size %s byte) has been deleted --]\n",
834 "[-- This %s/%s attachment (size %s bytes) has been deleted --]\n", size);
835 }
836 }
837 else
838 {
839 pretty_size[0] = '\0';
840 if (expire != -1)
841 {
842 /* L10N: If the translation of this string is a multi line string, then
843 each line should start with "[-- " and end with " --]".
844 The first "%s/%s" is a MIME type, e.g. "text/plain". The last %s
845 expands to a date as returned by `mutt_date_parse_date()`.
846
847 Caution: Argument three %3$ is also defined but should not be used
848 in this translation! */
849 str = _("[-- This %s/%s attachment has been deleted --]\n[-- on %4$s --]\n");
850 }
851 else
852 {
853 /* L10N: If the translation of this string is a multi line string, then
854 each line should start with "[-- " and end with " --]".
855 The first "%s/%s" is a MIME type, e.g. "text/plain". */
856 str = _("[-- This %s/%s attachment has been deleted --]\n");
857 }
858 }
859
860 snprintf(strbuf, sizeof(strbuf), str, TYPE(b->parts), b->parts->subtype,
861 pretty_size, expiration);
862 state_attach_puts(s, strbuf);
863 if (b->parts->filename)
864 {
866 state_printf(s, _("[-- name: %s --]\n"), b->parts->filename);
867 }
868
869 CopyHeaderFlags chflags = CH_DECODE;
870 if (c_weed)
871 chflags |= CH_WEED | CH_REORDER;
872
873 mutt_copy_hdr(s->fp_in, s->fp_out, ftello(s->fp_in), b->parts->offset,
874 chflags, NULL, 0);
875 }
876 }
877 else if (expiration && (expire < mutt_date_epoch()))
878 {
879 if (s->flags & MUTT_DISPLAY)
880 {
881 /* L10N: If the translation of this string is a multi line string, then
882 each line should start with "[-- " and end with " --]".
883 The "%s/%s" is a MIME type, e.g. "text/plain". */
884 snprintf(strbuf, sizeof(strbuf),
885 _("[-- This %s/%s attachment is not included, --]\n[-- and the indicated external source has --]\n[-- expired. --]\n"),
886 TYPE(b->parts), b->parts->subtype);
887 state_attach_puts(s, strbuf);
888
890 if (c_weed)
891 chflags |= CH_WEED | CH_REORDER;
892
893 mutt_copy_hdr(s->fp_in, s->fp_out, ftello(s->fp_in), b->parts->offset,
894 chflags, NULL, 0);
895 }
896 }
897 else
898 {
899 if (s->flags & MUTT_DISPLAY)
900 {
901 /* L10N: If the translation of this string is a multi line string, then
902 each line should start with "[-- " and end with " --]".
903 The "%s/%s" is a MIME type, e.g. "text/plain". The %s after
904 access-type is an access-type as defined by the MIME RFCs, e.g. "FTP",
905 "LOCAL-FILE", "MAIL-SERVER". */
906 snprintf(strbuf, sizeof(strbuf),
907 _("[-- This %s/%s attachment is not included, --]\n[-- and the indicated access-type %s is unsupported --]\n"),
908 TYPE(b->parts), b->parts->subtype, access_type);
909 state_attach_puts(s, strbuf);
910
912 if (c_weed)
913 chflags |= CH_WEED | CH_REORDER;
914
915 mutt_copy_hdr(s->fp_in, s->fp_out, ftello(s->fp_in), b->parts->offset,
916 chflags, NULL, 0);
917 }
918 }
919
920 return 0;
921}
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:428
time_t mutt_date_parse_date(const char *s, struct Tz *tz_out)
Parse a date string in RFC822 format.
Definition: date.c:457
void state_attach_puts(struct State *s, const char *t)
Write a string to the state.
Definition: state.c:100
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:819
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1673
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ alternative_handler()

static int alternative_handler ( struct Body a,
struct State s 
)
static

Handler for multipart alternative emails - Implements handler_t -.

Definition at line 926 of file handler.c.

927{
928 struct Body *const head = a;
929 struct Body *choice = NULL;
930 struct Body *b = NULL;
931 bool mustfree = false;
932 int rc = 0;
933
934 if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
935 (a->encoding == ENC_UUENCODED))
936 {
937 mustfree = true;
938 b = mutt_body_new();
940 b->parts = mutt_parse_multipart(s->fp_in, mutt_param_get(&a->parameter, "boundary"),
941 b->length, mutt_istr_equal("digest", a->subtype));
942 }
943 else
944 b = a;
945
946 a = b;
947
948 /* First, search list of preferred types */
949 struct ListNode *np = NULL;
951 {
952 int btlen; /* length of basetype */
953 bool wild; /* do we have a wildcard to match all subtypes? */
954
955 char *c = strchr(np->data, '/');
956 if (c)
957 {
958 wild = ((c[1] == '*') && (c[2] == '\0'));
959 btlen = c - np->data;
960 }
961 else
962 {
963 wild = true;
964 btlen = mutt_str_len(np->data);
965 }
966
967 if (a->parts)
968 b = a->parts;
969 else
970 b = a;
971 while (b)
972 {
973 const char *bt = TYPE(b);
974 if (mutt_istrn_equal(bt, np->data, btlen) && (bt[btlen] == 0))
975 {
976 /* the basetype matches */
977 if (wild || mutt_istr_equal(np->data + btlen + 1, b->subtype))
978 {
979 choice = b;
980 }
981 }
982 b = b->next;
983 }
984
985 if (choice)
986 break;
987 }
988
989 /* Next, look for an autoviewable type */
990 if (!choice)
991 {
992 if (a->parts)
993 b = a->parts;
994 else
995 b = a;
996 while (b)
997 {
998 if (is_autoview(b))
999 choice = b;
1000 b = b->next;
1001 }
1002 }
1003
1004 /* Then, look for a text entry */
1005 if (!choice)
1006 {
1007 if (a->parts)
1008 b = a->parts;
1009 else
1010 b = a;
1011 int type = 0;
1012 while (b)
1013 {
1014 if (b->type == TYPE_TEXT)
1015 {
1016 if (mutt_istr_equal("plain", b->subtype) && (type <= TXT_PLAIN))
1017 {
1018 choice = b;
1019 type = TXT_PLAIN;
1020 }
1021 else if (mutt_istr_equal("enriched", b->subtype) && (type <= TXT_ENRICHED))
1022 {
1023 choice = b;
1024 type = TXT_ENRICHED;
1025 }
1026 else if (mutt_istr_equal("html", b->subtype) && (type <= TXT_HTML))
1027 {
1028 choice = b;
1029 type = TXT_HTML;
1030 }
1031 }
1032 b = b->next;
1033 }
1034 }
1035
1036 /* Finally, look for other possibilities */
1037 if (!choice)
1038 {
1039 if (a->parts)
1040 b = a->parts;
1041 else
1042 b = a;
1043 while (b)
1044 {
1045 if (mutt_can_decode(b))
1046 choice = b;
1047 b = b->next;
1048 }
1049 }
1050
1051 if (choice)
1052 {
1053 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
1054 if (s->flags & MUTT_DISPLAY && !c_weed &&
1055 mutt_file_seek(s->fp_in, choice->hdr_offset, SEEK_SET))
1056 {
1057 mutt_file_copy_bytes(s->fp_in, s->fp_out, choice->offset - choice->hdr_offset);
1058 }
1059
1060 const char *const c_show_multipart_alternative = cs_subset_string(NeoMutt->sub, "show_multipart_alternative");
1061 if (mutt_str_equal("info", c_show_multipart_alternative))
1062 {
1063 print_part_line(s, choice, 0);
1064 }
1065 mutt_body_handler(choice, s);
1066
1067 /* Let it flow back to the main part */
1068 head->nowrap = choice->nowrap;
1069 choice->nowrap = false;
1070
1071 if (mutt_str_equal("info", c_show_multipart_alternative))
1072 {
1073 if (a->parts)
1074 b = a->parts;
1075 else
1076 b = a;
1077 int count = 0;
1078 while (b)
1079 {
1080 if (choice != b)
1081 {
1082 count += 1;
1083 if (count == 1)
1084 state_putc(s, '\n');
1085
1086 print_part_line(s, b, count);
1087 }
1088 b = b->next;
1089 }
1090 }
1091 }
1092 else if (s->flags & MUTT_DISPLAY)
1093 {
1094 /* didn't find anything that we could display! */
1096 state_puts(s, _("[-- Error: Could not display any parts of Multipart/Alternative --]\n"));
1097 rc = -1;
1098 }
1099
1100 if (mustfree)
1101 mutt_body_free(&a);
1102
1103 return rc;
1104}
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:690
static bool is_autoview(struct Body *b)
Should email body be filtered by mailcap.
Definition: handler.c:478
bool mutt_can_decode(struct Body *b)
Will decoding the attachment produce any output.
Definition: handler.c:1827
static void print_part_line(struct State *s, struct Body *b, int n)
Print a separator for the Mime part.
Definition: handler.c:88
#define TXT_PLAIN
Definition: handler.c:67
#define TXT_HTML
Definition: handler.c:66
#define TXT_ENRICHED
Definition: handler.c:68
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:524
struct ListHead AlternativeOrderList
List of preferred mime types to display.
Definition: mutt_globals.h:60
struct Body * mutt_parse_multipart(FILE *fp, const char *boundary, LOFF_T end_off, bool digest)
Parse a multipart structure.
Definition: parse.c:1767
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
bool nowrap
Do not wrap the output in the pager.
Definition: body.h:88
struct Body * next
next attachment in the list
Definition: body.h:71
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:80
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ multilingual_handler()

static int multilingual_handler ( struct Body a,
struct State s 
)
static

Handler for multi-lingual emails - Implements handler_t -.

Return values
0Always

Definition at line 1110 of file handler.c.

1111{
1112 struct Body *b = NULL;
1113 bool mustfree = false;
1114 int rc = 0;
1115
1116 mutt_debug(LL_DEBUG2, "RFC8255 >> entering in handler multilingual handler\n");
1117 if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
1118 (a->encoding == ENC_UUENCODED))
1119 {
1120 mustfree = true;
1121 b = mutt_body_new();
1123 b->parts = mutt_parse_multipart(s->fp_in, mutt_param_get(&a->parameter, "boundary"),
1124 b->length, mutt_istr_equal("digest", a->subtype));
1125 }
1126 else
1127 b = a;
1128
1129 a = b;
1130
1131 if (a->parts)
1132 b = a->parts;
1133 else
1134 b = a;
1135
1136 struct Body *choice = NULL;
1137 struct Body *first_part = NULL;
1138 struct Body *zxx_part = NULL;
1139 struct ListNode *np = NULL;
1140
1141 while (b)
1142 {
1143 if (mutt_can_decode(b))
1144 {
1145 first_part = b;
1146 break;
1147 }
1148 b = b->next;
1149 }
1150
1151 const struct Slist *c_preferred_languages = cs_subset_slist(NeoMutt->sub, "preferred_languages");
1152 if (c_preferred_languages)
1153 {
1154 struct Buffer *langs = mutt_buffer_pool_get();
1155 cs_subset_str_string_get(NeoMutt->sub, "preferred_languages", langs);
1156 mutt_debug(LL_DEBUG2, "RFC8255 >> preferred_languages set in config to '%s'\n",
1157 mutt_buffer_string(langs));
1159
1160 STAILQ_FOREACH(np, &c_preferred_languages->head, entries)
1161 {
1162 while (b)
1163 {
1164 if (mutt_can_decode(b))
1165 {
1166 if (b->language && mutt_str_equal("zxx", b->language))
1167 zxx_part = b;
1168
1169 mutt_debug(LL_DEBUG2, "RFC8255 >> comparing configuration preferred_language='%s' to mail part content-language='%s'\n",
1170 np->data, b->language);
1171 if (b->language && mutt_str_equal(np->data, b->language))
1172 {
1173 mutt_debug(LL_DEBUG2, "RFC8255 >> preferred_language='%s' matches content-language='%s' >> part selected to be displayed\n",
1174 np->data, b->language);
1175 choice = b;
1176 break;
1177 }
1178 }
1179
1180 b = b->next;
1181 }
1182
1183 if (choice)
1184 break;
1185
1186 if (a->parts)
1187 b = a->parts;
1188 else
1189 b = a;
1190 }
1191 }
1192
1193 if (choice)
1194 mutt_body_handler(choice, s);
1195 else
1196 {
1197 if (zxx_part)
1198 mutt_body_handler(zxx_part, s);
1199 else
1200 mutt_body_handler(first_part, s);
1201 }
1202
1203 if (mustfree)
1204 mutt_body_free(&a);
1205
1206 return rc;
1207}
const struct Slist * cs_subset_slist(const struct ConfigSubset *sub, const char *name)
Get a string-list config item by name.
Definition: helpers.c:268
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
char * language
content-language (RFC8255)
Definition: body.h:77
String list.
Definition: slist.h:47
struct ListHead head
List containing values.
Definition: slist.h:48
int cs_subset_str_string_get(const struct ConfigSubset *sub, const char *name, struct Buffer *result)
Get a config item as a string.
Definition: subset.c:370
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ multipart_handler()

static int multipart_handler ( struct Body a,
struct State s 
)
static

Handler for multipart emails - Implements handler_t -.

Definition at line 1212 of file handler.c.

1213{
1214 struct Body *b = NULL, *p = NULL;
1215 int count;
1216 int rc = 0;
1217
1218 if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
1219 (a->encoding == ENC_UUENCODED))
1220 {
1221 b = mutt_body_new();
1223 b->parts = mutt_parse_multipart(s->fp_in, mutt_param_get(&a->parameter, "boundary"),
1224 b->length, mutt_istr_equal("digest", a->subtype));
1225 }
1226 else
1227 b = a;
1228
1229 for (p = b->parts, count = 1; p; p = p->next, count++)
1230 {
1231 if (s->flags & MUTT_DISPLAY)
1232 {
1234 if (p->description || p->filename || p->form_name)
1235 {
1236 /* L10N: %s is the attachment description, filename or form_name. */
1237 state_printf(s, _("[-- Attachment #%d: %s --]\n"), count,
1238 p->description ? p->description :
1239 p->filename ? p->filename :
1240 p->form_name);
1241 }
1242 else
1243 state_printf(s, _("[-- Attachment #%d --]\n"), count);
1244 print_part_line(s, p, 0);
1245 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
1246 if (c_weed)
1247 {
1248 state_putc(s, '\n');
1249 }
1250 else if (mutt_file_seek(s->fp_in, p->hdr_offset, SEEK_SET))
1251 {
1252 mutt_file_copy_bytes(s->fp_in, s->fp_out, p->offset - p->hdr_offset);
1253 }
1254 }
1255
1256 rc = mutt_body_handler(p, s);
1257 state_putc(s, '\n');
1258
1259 if (rc != 0)
1260 {
1261 mutt_error(_("One or more parts of this message could not be displayed"));
1262 mutt_debug(LL_DEBUG1, "Failed on attachment #%d, type %s/%s\n", count,
1263 TYPE(p), NONULL(p->subtype));
1264 }
1265
1266 const bool c_include_only_first = cs_subset_bool(NeoMutt->sub, "include_only_first");
1267 if ((s->flags & MUTT_REPLYING) && c_include_only_first && (s->flags & MUTT_FIRSTDONE))
1268 {
1269 break;
1270 }
1271 }
1272
1273 if ((a->encoding == ENC_BASE64) || (a->encoding == ENC_QUOTED_PRINTABLE) ||
1274 (a->encoding == ENC_UUENCODED))
1275 {
1276 mutt_body_free(&b);
1277 }
1278
1279 /* make failure of a single part non-fatal */
1280 if (rc < 0)
1281 rc = 1;
1282 return rc;
1283}
#define mutt_error(...)
Definition: logging.h:87
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
#define MUTT_FIRSTDONE
The first attachment has been done.
Definition: state.h:39
#define MUTT_REPLYING
Are we replying?
Definition: state.h:38
#define NONULL(x)
Definition: string2.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ valid_pgp_encrypted_handler()

static int valid_pgp_encrypted_handler ( struct Body b,
struct State s 
)
static

Handler for valid pgp-encrypted emails - Implements handler_t -.

Definition at line 1437 of file handler.c.

1438{
1439 struct Body *octetstream = b->parts->next;
1440
1441 /* clear out any mime headers before the handler, so they can't be spoofed. */
1443 mutt_env_free(&octetstream->mime_headers);
1444
1445 int rc;
1446 /* Some clients improperly encode the octetstream part. */
1447 if (octetstream->encoding != ENC_7BIT)
1448 rc = run_decode_and_handler(octetstream, s, crypt_pgp_encrypted_handler, 0);
1449 else
1450 rc = crypt_pgp_encrypted_handler(octetstream, s);
1451 b->goodsig |= octetstream->goodsig;
1452
1453 /* Relocate protected headers onto the multipart/encrypted part */
1454 if (!rc && octetstream->mime_headers)
1455 {
1456 b->mime_headers = octetstream->mime_headers;
1457 octetstream->mime_headers = NULL;
1458 }
1459
1460 return rc;
1461}
void mutt_env_free(struct Envelope **ptr)
Free an Envelope.
Definition: envelope.c:97
int crypt_pgp_encrypted_handler(struct Body *b, struct State *s)
Wrapper for CryptModuleSpecs::encrypted_handler() - Implements handler_t -.
Definition: cryptglue.c:248
static int run_decode_and_handler(struct Body *b, struct State *s, handler_t handler, bool plaintext)
Run an appropriate decoder for an email.
Definition: handler.c:1294
@ ENC_7BIT
7-bit text
Definition: mime.h:49
struct Envelope * mime_headers
Memory hole protected headers.
Definition: body.h:75
bool goodsig
Good cryptographic signature.
Definition: body.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ malformed_pgp_encrypted_handler()

static int malformed_pgp_encrypted_handler ( struct Body b,
struct State s 
)
static

Handler for invalid pgp-encrypted emails - Implements handler_t -.

Definition at line 1466 of file handler.c.

1467{
1468 struct Body *octetstream = b->parts->next->next;
1469
1470 /* clear out any mime headers before the handler, so they can't be spoofed. */
1472 mutt_env_free(&octetstream->mime_headers);
1473
1474 /* exchange encodes the octet-stream, so re-run it through the decoder */
1475 int rc = run_decode_and_handler(octetstream, s, crypt_pgp_encrypted_handler, false);
1476 b->goodsig |= octetstream->goodsig;
1477#ifdef USE_AUTOCRYPT
1478 b->is_autocrypt |= octetstream->is_autocrypt;
1479#endif
1480
1481 /* Relocate protected headers onto the multipart/encrypted part */
1482 if (!rc && octetstream->mime_headers)
1483 {
1484 b->mime_headers = octetstream->mime_headers;
1485 octetstream->mime_headers = NULL;
1486 }
1487
1488 return rc;
1489}
bool is_autocrypt
Flag autocrypt-decrypted messages for replying.
Definition: body.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_protected_headers_handler()

int mutt_protected_headers_handler ( struct Body b,
struct State s 
)

Process a protected header - Implements handler_t -.

Definition at line 1095 of file crypt.c.

1096{
1097 const bool c_crypt_protected_headers_read = cs_subset_bool(NeoMutt->sub, "crypt_protected_headers_read");
1098 if (c_crypt_protected_headers_read && b->mime_headers)
1099 {
1100 if (b->mime_headers->subject)
1101 {
1102 const bool display = (s->flags & MUTT_DISPLAY);
1103
1104 const bool c_weed = cs_subset_bool(NeoMutt->sub, "weed");
1105 if (display && c_weed && mutt_matches_ignore("subject"))
1106 return 0;
1107
1109 const short c_wrap = cs_subset_number(NeoMutt->sub, "wrap");
1110 int wraplen = display ? mutt_window_wrap_cols(s->wraplen, c_wrap) : 0;
1111
1113 wraplen, display ? CH_DISPLAY : CH_NO_FLAGS, NeoMutt->sub);
1114 state_puts(s, "\n");
1115 }
1116 }
1117
1118 return 0;
1119}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition: helpers.c:169
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:51
int mutt_write_one_header(FILE *fp, const char *tag, const char *value, const char *pfx, int wraplen, CopyHeaderFlags chflags, struct ConfigSubset *sub)
Write one header line to a file.
Definition: header.c:420
void state_mark_protected_header(struct State *s)
Write a unique marker around protected headers.
Definition: state.c:86
int mutt_window_wrap_cols(int width, short wrap)
Calculate the wrap column for a given screen width.
Definition: mutt_window.c:365
bool mutt_matches_ignore(const char *s)
Does the string match the ignore list.
Definition: parse.c:313
char * subject
Email's subject.
Definition: envelope.h:70
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_signed_handler()

int mutt_signed_handler ( struct Body b,
struct State s 
)

Verify a "multipart/signed" body - Implements handler_t -.

Definition at line 1124 of file crypt.c.

1125{
1126 if (!WithCrypto)
1127 return -1;
1128
1129 bool inconsistent = false;
1130 struct Body *top = b;
1131 struct Body **signatures = NULL;
1132 int sigcnt = 0;
1133 int rc = 0;
1134 struct Buffer *tempfile = NULL;
1135
1136 b = b->parts;
1137 SecurityFlags signed_type = mutt_is_multipart_signed(top);
1138 if (signed_type == SEC_NO_FLAGS)
1139 {
1140 /* A null protocol value is already checked for in mutt_body_handler() */
1141 state_printf(s, _("[-- Error: Unknown multipart/signed protocol %s --]\n\n"),
1142 mutt_param_get(&top->parameter, "protocol"));
1143 return mutt_body_handler(b, s);
1144 }
1145
1146 if (!(b && b->next))
1147 inconsistent = true;
1148 else
1149 {
1150 switch (signed_type)
1151 {
1152 case SEC_SIGN:
1153 if ((b->next->type != TYPE_MULTIPART) || !mutt_istr_equal(b->next->subtype, "mixed"))
1154 {
1155 inconsistent = true;
1156 }
1157 break;
1158 case PGP_SIGN:
1159 if ((b->next->type != TYPE_APPLICATION) ||
1160 !mutt_istr_equal(b->next->subtype, "pgp-signature"))
1161 {
1162 inconsistent = true;
1163 }
1164 break;
1165 case SMIME_SIGN:
1166 if ((b->next->type != TYPE_APPLICATION) ||
1167 (!mutt_istr_equal(b->next->subtype, "x-pkcs7-signature") &&
1168 !mutt_istr_equal(b->next->subtype, "pkcs7-signature")))
1169 {
1170 inconsistent = true;
1171 }
1172 break;
1173 default:
1174 inconsistent = true;
1175 }
1176 }
1177 if (inconsistent)
1178 {
1179 state_attach_puts(s, _("[-- Error: Missing or bad-format multipart/signed signature --]\n\n"));
1180 return mutt_body_handler(b, s);
1181 }
1182
1183 if (s->flags & MUTT_DISPLAY)
1184 {
1185 crypt_fetch_signatures(&signatures, b->next, &sigcnt);
1186
1187 if (sigcnt != 0)
1188 {
1189 tempfile = mutt_buffer_pool_get();
1190 mutt_buffer_mktemp(tempfile);
1191 bool goodsig = true;
1192 if (crypt_write_signed(b, s, mutt_buffer_string(tempfile)) == 0)
1193 {
1194 for (int i = 0; i < sigcnt; i++)
1195 {
1196 if (((WithCrypto & APPLICATION_PGP) != 0) &&
1197 (signatures[i]->type == TYPE_APPLICATION) &&
1198 mutt_istr_equal(signatures[i]->subtype, "pgp-signature"))
1199 {
1200 if (crypt_pgp_verify_one(signatures[i], s, mutt_buffer_string(tempfile)) != 0)
1201 goodsig = false;
1202
1203 continue;
1204 }
1205
1206 if (((WithCrypto & APPLICATION_SMIME) != 0) &&
1207 (signatures[i]->type == TYPE_APPLICATION) &&
1208 (mutt_istr_equal(signatures[i]->subtype, "x-pkcs7-signature") ||
1209 mutt_istr_equal(signatures[i]->subtype, "pkcs7-signature")))
1210 {
1211 if (crypt_smime_verify_one(signatures[i], s, mutt_buffer_string(tempfile)) != 0)
1212 goodsig = false;
1213
1214 continue;
1215 }
1216
1217 state_printf(s, _("[-- Warning: We can't verify %s/%s signatures. --]\n\n"),
1218 TYPE(signatures[i]), signatures[i]->subtype);
1219 }
1220 }
1221
1223 mutt_buffer_pool_release(&tempfile);
1224
1225 top->goodsig = goodsig;
1226 top->badsig = !goodsig;
1227
1228 /* Now display the signed body */
1229 state_attach_puts(s, _("[-- The following data is signed --]\n\n"));
1230
1232
1233 FREE(&signatures);
1234 }
1235 else
1236 {
1237 state_attach_puts(s, _("[-- Warning: Can't find any signatures. --]\n\n"));
1238 }
1239 }
1240
1241 rc = mutt_body_handler(b, s);
1242
1243 if ((s->flags & MUTT_DISPLAY) && (sigcnt != 0))
1244 state_attach_puts(s, _("\n[-- End of signed data --]\n"));
1245
1246 return rc;
1247}
int crypt_write_signed(struct Body *a, struct State *s, const char *tempfile)
Write the message body/part.
Definition: crypt.c:747
SecurityFlags mutt_is_multipart_signed(struct Body *b)
Is a message signed?
Definition: crypt.c:402
static void crypt_fetch_signatures(struct Body ***signatures, struct Body *a, int *n)
Create an array of an emails parts.
Definition: crypt.c:1054
int crypt_smime_verify_one(struct Body *sigbdy, struct State *s, const char *tempf)
Wrapper for CryptModuleSpecs::verify_one()
Definition: cryptglue.c:517
int crypt_pgp_verify_one(struct Body *sigbdy, struct State *s, const char *tempf)
Wrapper for CryptModuleSpecs::verify_one()
Definition: cryptglue.c:373
int mutt_protected_headers_handler(struct Body *b, struct State *s)
Process a protected header - Implements handler_t -.
Definition: crypt.c:1095
@ TYPE_MULTIPART
Type: 'multipart/*'.
Definition: mime.h:37
@ TYPE_APPLICATION
Type: 'application/*'.
Definition: mime.h:33
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:74
#define PGP_SIGN
Definition: lib.h:97
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:76
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:90
#define SMIME_SIGN
Definition: lib.h:103
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:91
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:77
#define WithCrypto
Definition: lib.h:116
#define SEC_SIGN
Email is signed.
Definition: lib.h:79
bool badsig
Bad cryptographic signature (needed to check encrypted s/mime-signatures)
Definition: body.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_pgp_application_handler()

int crypt_pgp_application_handler ( struct Body b,
struct State s 
)

Wrapper for CryptModuleSpecs::application_handler() - Implements handler_t -.

Definition at line 237 of file cryptglue.c.

238{
239 if (CRYPT_MOD_CALL_CHECK(PGP, application_handler))
240 return CRYPT_MOD_CALL(PGP, application_handler)(b, s);
241
242 return -1;
243}
#define CRYPT_MOD_CALL_CHECK(identifier, func)
Definition: cryptglue.c:80
#define CRYPT_MOD_CALL(identifier, func)
Definition: cryptglue.c:86
+ Here is the caller graph for this function:

◆ crypt_pgp_encrypted_handler()

int crypt_pgp_encrypted_handler ( struct Body b,
struct State s 
)

Wrapper for CryptModuleSpecs::encrypted_handler() - Implements handler_t -.

Definition at line 248 of file cryptglue.c.

249{
250#ifdef USE_AUTOCRYPT
251 const bool c_autocrypt = cs_subset_bool(NeoMutt->sub, "autocrypt");
252 if (c_autocrypt)
253 {
254 OptAutocryptGpgme = true;
255 int result = pgp_gpgme_encrypted_handler(b, s);
256 OptAutocryptGpgme = false;
257 if (result == 0)
258 {
259 b->is_autocrypt = true;
260 return result;
261 }
262 }
263#endif
264
265 if (CRYPT_MOD_CALL_CHECK(PGP, encrypted_handler))
266 return CRYPT_MOD_CALL(PGP, encrypted_handler)(b, s);
267
268 return -1;
269}
int pgp_gpgme_encrypted_handler(struct Body *a, struct State *s)
Implements CryptModuleSpecs::encrypted_handler() -.
Definition: crypt_gpgme.c:2650
bool OptAutocryptGpgme
(pseudo) use Autocrypt context inside ncrypt/crypt_gpgme.c
Definition: options.h:39
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crypt_smime_application_handler()

int crypt_smime_application_handler ( struct Body b,
struct State s 
)

Wrapper for CryptModuleSpecs::application_handler() - Implements handler_t -.

Definition at line 444 of file cryptglue.c.

445{
446 if (CRYPT_MOD_CALL_CHECK(SMIME, application_handler))
447 return CRYPT_MOD_CALL(SMIME, application_handler)(b, s);
448
449 return -1;
450}
+ Here is the caller graph for this function:

◆ rfc3676_handler()

int rfc3676_handler ( struct Body a,
struct State s 
)

Body handler implementing RFC3676 for format=flowed - Implements handler_t -.

Return values
0Always

Definition at line 318 of file rfc3676.c.

319{
320 char *buf = NULL;
321 unsigned int quotelevel = 0;
322 bool delsp = false;
323 size_t sz = 0;
324 struct FlowedState fst = { 0 };
325
326 /* respect DelSp of RFC3676 only with f=f parts */
327 char *t = mutt_param_get(&a->parameter, "delsp");
328 if (t)
329 {
330 delsp = mutt_istr_equal(t, "yes");
331 t = NULL;
332 fst.delsp = true;
333 }
334
335 mutt_debug(LL_DEBUG3, "f=f: DelSp: %s\n", delsp ? "yes" : "no");
336
337 while ((buf = mutt_file_read_line(buf, &sz, s->fp_in, NULL, MUTT_RL_NO_FLAGS)))
338 {
339 const size_t buf_len = mutt_str_len(buf);
340 const unsigned int newql = get_quote_level(buf);
341
342 /* end flowed paragraph (if we're within one) if quoting level
343 * changes (should not but can happen, see RFC3676, sec. 4.5.) */
344 if (newql != quotelevel)
345 flush_par(s, &fst);
346
347 quotelevel = newql;
348 int buf_off = newql;
349
350 /* respect sender's space-stuffing by removing one leading space */
351 if (buf[buf_off] == ' ')
352 buf_off++;
353
354 /* test for signature separator */
355 const unsigned int sigsep = mutt_str_equal(buf + buf_off, "-- ");
356
357 /* a fixed line either has no trailing space or is the
358 * signature separator */
359 const bool fixed = (buf_len == buf_off) || (buf[buf_len - 1] != ' ') || sigsep;
360
361 /* print fixed-and-standalone, fixed-and-empty and sigsep lines as
362 * fixed lines */
363 if ((fixed && ((fst.width == 0) || (buf_len == 0))) || sigsep)
364 {
365 /* if we're within a flowed paragraph, terminate it */
366 flush_par(s, &fst);
367 print_fixed_line(buf + buf_off, s, quotelevel, &fst);
368 continue;
369 }
370
371 /* for DelSp=yes, we need to strip one SP prior to CRLF on flowed lines */
372 if (delsp && !fixed)
373 buf[buf_len - 1] = '\0';
374
375 print_flowed_line(buf + buf_off, s, quotelevel, &fst, fixed);
376 }
377
378 flush_par(s, &fst);
379
380 FREE(&buf);
381 return 0;
382}
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
static void print_fixed_line(const char *line, struct State *s, int ql, struct FlowedState *fst)
Print a fixed format line.
Definition: rfc3676.c:303
static void print_flowed_line(char *line, struct State *s, int ql, struct FlowedState *fst, bool term)
Print a format-flowed line.
Definition: rfc3676.c:224
static int get_quote_level(const char *line)
Get the quote level of a line.
Definition: rfc3676.c:61
static void flush_par(struct State *s, struct FlowedState *fst)
Write out the paragraph.
Definition: rfc3676.c:171
State of a Format-Flowed line of text.
Definition: rfc3676.c:50
bool delsp
Definition: rfc3676.c:53
size_t width
Definition: rfc3676.c:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function: