On Thu, Apr 26, 2018 at 4:23 PM, Kevin J. McCarthy <ke...@8t8.us> wrote: > > diff --git a/doc/manual.xml.head b/doc/manual.xml.head > > > +<row><entry>~M <emphasis>EXPR</emphasis></entry><entry>messages which > > contain a mime Content-Type matching <emphasis>EXPR</emphasis></entry></row> > > +<row><entry>=M <emphasis>STRING</emphasis></entry><entry>messages > > which contain a mime Content-Type containing > > <emphasis>STRING</emphasis></entry></row> > > There is no need to add '=M' documentation. This is covered below in > the documentation where it says: > You can force Mutt to treat EXPR as a simple string instead of a > regular expression by using = instead of ~ in the pattern name." > > The =b/=B/=h are explicity mentioned because of their IMAP behavior.
I did copy the =b/=B. I hadn't considered IMAP for this feature, as I'm not using it. Since we have to parse the message to match content-type, how would this behave under IMAP? Would it work on the server, or does it have to be local? If it can work on the server, then perhaps I should distinguish that -- I can imagine an IMAP user might not want to download large PDF-containing messages while performing this limit. I'll remove the =M lines for now. > > diff --git a/pattern.c b/pattern.c > > +static int match_content_type(const pattern_t* pat, BODY *b) > > +{ > > + char buffer[STRING]; > > + if (b == 0) > > + return 0; > > We more commonly compare to NULL or just !b in the mutt source code. Fixed. > > + if (snprintf(buffer, STRING, "%s/%s", TYPE (b), b->subtype) >= STRING) > > + buffer[STRING-1] = '\0'; > > + > > + if (b->subtype != 0 && (patmatch (pat, buffer) == 0)) > > + return 1; > > I don't believe subtype should be NULL. Is the check necessary? Looks like mutt_parse_content_type() always sets subtype to a non-NULL value. Check has been dropped (and it was in the wrong place anyway, since by this point it's baked into buffer). Updated patch attached. A
diff --git a/doc/manual.xml.head b/doc/manual.xml.head index 0188803..7f75d0e 100644 --- a/doc/manual.xml.head +++ b/doc/manual.xml.head @@ -5199,6 +5199,7 @@ shows several ways to select messages. <row><entry>%L <emphasis>GROUP</emphasis></entry><entry>message either originated or received by any member of <emphasis>GROUP</emphasis></entry></row> <row><entry>~l</entry><entry>messages addressed to a known mailing list</entry></row> <row><entry>~m [<emphasis>MIN</emphasis>]-[<emphasis>MAX</emphasis>]</entry><entry>messages in the range <emphasis>MIN</emphasis> to <emphasis>MAX</emphasis> *)</entry></row> +<row><entry>~M <emphasis>EXPR</emphasis></entry><entry>messages which contain a mime Content-Type matching <emphasis>EXPR</emphasis></entry></row> <row><entry>~n [<emphasis>MIN</emphasis>]-[<emphasis>MAX</emphasis>]</entry><entry>messages with a score in the range <emphasis>MIN</emphasis> to <emphasis>MAX</emphasis> *)</entry></row> <row><entry>~N</entry><entry>new messages</entry></row> <row><entry>~O</entry><entry>old messages</entry></row> diff --git a/doc/muttrc.man.head b/doc/muttrc.man.head index 28591f0..f73e5cf 100644 --- a/doc/muttrc.man.head +++ b/doc/muttrc.man.head @@ -575,6 +575,9 @@ messages either originated or received by any member of \fIGROUP\fP ~m \fIMIN\fP-\fIMAX\fP message in the range \fIMIN\fP to \fIMAX\fP .TP +~M \fIEXPR\fP +messages which contain a mime Content-Type matching \fIEXPR\fP +.TP ~n \fIMIN\fP-\fIMAX\fP messages with a score in the range \fIMIN\fP to \fIMAX\fP .TP diff --git a/mutt.h b/mutt.h index 4fe7ce4..7c5bec2 100644 --- a/mutt.h +++ b/mutt.h @@ -253,6 +253,7 @@ enum MUTT_PGP_KEY, MUTT_XLABEL, MUTT_MIMEATTACH, + MUTT_MIMETYPE, /* Options for Mailcap lookup */ MUTT_EDIT, diff --git a/pattern.c b/pattern.c index 285cbfa..7aa4896 100644 --- a/pattern.c +++ b/pattern.c @@ -25,6 +25,7 @@ #include "keymap.h" #include "mailbox.h" #include "copy.h" +#include "mime.h" #include <string.h> #include <stdlib.h> @@ -76,6 +77,7 @@ Flags[] = { 'l', MUTT_LIST, 0, NULL }, { 'L', MUTT_ADDRESS, 0, eat_regexp }, { 'm', MUTT_MESSAGE, 0, eat_range }, + { 'M', MUTT_MIMETYPE, MUTT_FULL_MSG, eat_regexp }, { 'n', MUTT_SCORE, 0, eat_range }, { 'N', MUTT_NEW, 0, NULL }, { 'O', MUTT_OLD, 0, NULL }, @@ -1138,6 +1140,29 @@ static int match_threadchildren(struct pattern_t *pat, pattern_exec_flag flags, return 0; } +static int match_content_type(const pattern_t* pat, BODY *b) +{ + char buffer[STRING]; + if (!b) + return 0; + + if (snprintf(buffer, STRING, "%s/%s", TYPE (b), b->subtype) >= STRING) + buffer[STRING-1] = '\0'; + + if (patmatch (pat, buffer) == 0) + return 1; + if (match_content_type (pat, b->parts)) + return 1; + if (match_content_type (pat, b->next)) + return 1; + return 0; +} + +static int match_mime_content_type(const pattern_t *pat, CONTEXT *ctx, HEADER *hdr) +{ + mutt_parse_mime_message(ctx, hdr); + return match_content_type(pat, hdr->content); +} /* Sets a value in the pattern_cache_t cache entry. * Normalizes the "true" value to 2. */ @@ -1158,7 +1183,6 @@ static int is_pattern_cache_set (int cache_entry) return cache_entry != 0; } - /* * flags: MUTT_MATCH_FULL_ADDRESS - match both personal and machine address * cache: For repeated matches against the same HEADER, passing in non-NULL will @@ -1338,6 +1362,10 @@ mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, return (pat->not ^ (count >= pat->min && (pat->max == MUTT_MAXRANGE || count <= pat->max))); } + case MUTT_MIMETYPE: + if (!ctx) + return 0; + return (pat->not ^ match_mime_content_type (pat, ctx, h)); case MUTT_UNREFERENCED: return (pat->not ^ (h->thread && !h->thread->child)); }