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));
   }

Reply via email to