NeoMutt  2018-07-16 +952-a2da0a
Teaching an old dog new tricks
DOXYGEN
pattern.c File Reference

Match patterns to emails. More...

#include "config.h"
#include <stddef.h>
#include <ctype.h>
#include <regex.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include "mutt/mutt.h"
#include "config/lib.h"
#include "email/lib.h"
#include "conn/conn.h"
#include "mutt.h"
#include "pattern.h"
#include "alias.h"
#include "context.h"
#include "copy.h"
#include "curs_lib.h"
#include "globals.h"
#include "group.h"
#include "handler.h"
#include "hdrline.h"
#include "mailbox.h"
#include "menu.h"
#include "mutt_logging.h"
#include "mutt_parse.h"
#include "muttlib.h"
#include "mx.h"
#include "ncrypt/ncrypt.h"
#include "opcodes.h"
#include "options.h"
#include "progress.h"
#include "protos.h"
#include "state.h"
#include "imap/imap.h"
+ Include dependency graph for pattern.c:

Go to the source code of this file.

Data Structures

struct  RangeRegex
 Regular expression representing a range. More...
 
struct  PatternFlags
 Mapping between user character and internal constant. More...
 

Macros

#define RANGE_NUM_RX   "([[:digit:]]+|0x[[:xdigit:]]+)[MmKk]?"
 
#define RANGE_REL_SLOT_RX   "[[:blank:]]*([.^$]|-?" RANGE_NUM_RX ")?[[:blank:]]*"
 
#define RANGE_REL_RX   "^" RANGE_REL_SLOT_RX "," RANGE_REL_SLOT_RX
 
#define RANGE_ABS_SLOT_RX   "[[:blank:]]*([.^$]|" RANGE_NUM_RX ")?[[:blank:]]*"
 
#define RANGE_ABS_RX   "^" RANGE_ABS_SLOT_RX "-" RANGE_ABS_SLOT_RX
 
#define RANGE_LT_RX   "^()[[:blank:]]*(<[[:blank:]]*" RANGE_NUM_RX ")[[:blank:]]*"
 
#define RANGE_GT_RX   "^()[[:blank:]]*(>[[:blank:]]*" RANGE_NUM_RX ")[[:blank:]]*"
 
#define RANGE_BARE_RX   "^[[:blank:]]*([.^$]|" RANGE_NUM_RX ")[[:blank:]]*"
 
#define RANGE_RX_GROUPS   5
 
#define KILO   1024
 
#define MEGA   1048576
 
#define HMSG(h)   (((h)->msgno) + 1)
 
#define CTX_MSGNO(c)   (HMSG((c)->mailbox->hdrs[(c)->mailbox->v2r[(c)->menu->current]]))
 
#define MUTT_MAXRANGE   -1
 
#define MUTT_PDR_NONE   0x0000
 
#define MUTT_PDR_MINUS   0x0001
 
#define MUTT_PDR_PLUS   0x0002
 
#define MUTT_PDR_WINDOW   0x0004
 
#define MUTT_PDR_ABSOLUTE   0x0008
 
#define MUTT_PDR_DONE   0x0010
 
#define MUTT_PDR_ERROR   0x0100
 
#define MUTT_PDR_ERRORDONE   (MUTT_PDR_ERROR | MUTT_PDR_DONE)
 
#define RANGE_DOT   '.'
 
#define RANGE_CIRCUM   '^'
 
#define RANGE_DOLLAR   '$'
 
#define RANGE_LT   '<'
 
#define RANGE_GT   '>'
 

Enumerations

enum  EatRangeError { RANGE_E_OK, RANGE_E_SYNTAX, RANGE_E_CTX }
 Error codes for eat_range_by_regex() More...
 
enum  RangeType {
  RANGE_K_REL, RANGE_K_ABS, RANGE_K_LT, RANGE_K_GT,
  RANGE_K_BARE, RANGE_K_INVALID
}
 Type of range. More...
 
enum  RangeSide { RANGE_S_LEFT, RANGE_S_RIGHT }
 Which side of the range. More...
 

Functions

static bool eat_regex (struct Pattern *pat, struct Buffer *s, struct Buffer *err)
 Parse a regex. More...
 
static const char * get_offset (struct tm *tm, const char *s, int sign)
 Calculate a symbolic offset. More...
 
static const char * get_date (const char *s, struct tm *t, struct Buffer *err)
 Parse a (partial) date in dd/mm/yyyy format. More...
 
static const char * parse_date_range (const char *pc, struct tm *min, struct tm *max, bool have_min, struct tm *base_min, struct Buffer *err)
 Parse a date range. More...
 
static void adjust_date_range (struct tm *min, struct tm *max)
 Put a date range in the correct order. More...
 
static bool eat_date (struct Pattern *pat, struct Buffer *s, struct Buffer *err)
 Parse a date pattern. More...
 
static bool eat_range (struct Pattern *pat, struct Buffer *s, struct Buffer *err)
 Parse a number range. More...
 
static int report_regerror (int regerr, regex_t *preg, struct Buffer *err)
 Create a regex error message. More...
 
static bool is_context_available (struct Buffer *s, regmatch_t pmatch[], int kind, struct Buffer *err)
 Do we need a Context for this Pattern? More...
 
static int scan_range_num (struct Buffer *s, regmatch_t pmatch[], int group, int kind)
 Parse a number range. More...
 
static int scan_range_slot (struct Buffer *s, regmatch_t pmatch[], int grp, int side, int kind)
 Parse a range of message numbers. More...
 
static void order_range (struct Pattern *pat)
 Put a range in order. More...
 
static int eat_range_by_regex (struct Pattern *pat, struct Buffer *s, int kind, struct Buffer *err)
 Parse a range given as a regex. More...
 
static bool eat_message_range (struct Pattern *pat, struct Buffer *s, struct Buffer *err)
 Parse a range of message numbers. More...
 
static int patmatch (const struct Pattern *pat, const char *buf)
 Compare a string to a Pattern. More...
 
static bool msg_search (struct Mailbox *m, struct Pattern *pat, int msgno)
 Search an email. More...
 
static const struct PatternFlagslookup_tag (char tag)
 Lookup a pattern modifier. More...
 
static char * find_matching_paren (char *s)
 Find the matching parenthesis. More...
 
void mutt_pattern_free (struct Pattern **pat)
 Free a Pattern. More...
 
struct Patternmutt_pattern_new (void)
 Create a new Pattern. More...
 
struct Patternmutt_pattern_comp (char *s, int flags, struct Buffer *err)
 Create a Pattern. More...
 
static bool perform_and (struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
 Perform a logical AND on a set of Patterns. More...
 
static int perform_or (struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
 Perform a logical OR on a set of Patterns. More...
 
static int match_addrlist (struct Pattern *pat, bool match_personal, int n,...)
 Match a Pattern against and Address list. More...
 
static bool match_reference (struct Pattern *pat, struct ListHead *refs)
 Match references against a Pattern. More...
 
int mutt_is_list_recipient (bool alladdr, struct Address *a1, struct Address *a2)
 Matches subscribed mailing lists. More...
 
int mutt_is_list_cc (int alladdr, struct Address *a1, struct Address *a2)
 Matches known mailing lists. More...
 
static int match_user (int alladdr, struct Address *a1, struct Address *a2)
 Matches the user's email Address. More...
 
static int match_threadcomplete (struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct MuttThread *t, int left, int up, int right, int down)
 Match a Pattern against an email thread. More...
 
static int match_threadparent (struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct MuttThread *t)
 Match Pattern against an email's parent. More...
 
static int match_threadchildren (struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct MuttThread *t)
 Match Pattern against an email's children. More...
 
static int match_content_type (const struct Pattern *pat, struct Body *b)
 Match a Pattern against an Attachment's Content-Type. More...
 
static int match_mime_content_type (const struct Pattern *pat, struct Mailbox *m, struct Email *e)
 Match a Pattern against an email's Content-Type. More...
 
static void set_pattern_cache_value (int *cache_entry, int value)
 Sets a value in the PatternCache cache entry. More...
 
static int get_pattern_cache_value (int cache_entry)
 Get pattern cache value. More...
 
static int is_pattern_cache_set (int cache_entry)
 Is a given Pattern cached? More...
 
int mutt_pattern_exec (struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
 Match a pattern against an email header. More...
 
static void quote_simple (const char *str, char *buf, size_t buflen)
 Apply simple quoting to a string. More...
 
void mutt_check_simple (char *s, size_t len, const char *simple)
 Convert a simple search into a real request. More...
 
static struct MuttThreadtop_of_thread (struct Email *e)
 Find the first email in the current thread. More...
 
bool mutt_limit_current_thread (struct Email *e)
 Limit the email view to the current thread. More...
 
int mutt_pattern_func (int op, char *prompt)
 Perform some Pattern matching. More...
 
int mutt_search_command (int cur, int op)
 Perform a search. More...
 

Variables

bool ThoroughSearch
 Config: Decode headers and messages before searching them. More...
 
static struct RangeRegex range_regexes []
 Set of Regexes for various range types. More...
 
static struct PatternSearchPattern = NULL
 current search pattern More...
 
static char LastSearch [STRING] = { 0 }
 last pattern searched for More...
 
static char LastSearchExpn [LONG_STRING] = { 0 }
 expanded version of LastSearch More...
 
static const struct PatternFlags Flags []
 Lookup table for all patterns. More...
 

Detailed Description

Match patterns to emails.

Authors
  • Michael R. Elkins

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file pattern.c.

Macro Definition Documentation

#define RANGE_NUM_RX   "([[:digit:]]+|0x[[:xdigit:]]+)[MmKk]?"

Definition at line 75 of file pattern.c.

#define RANGE_REL_SLOT_RX   "[[:blank:]]*([.^$]|-?" RANGE_NUM_RX ")?[[:blank:]]*"

Definition at line 76 of file pattern.c.

#define RANGE_REL_RX   "^" RANGE_REL_SLOT_RX "," RANGE_REL_SLOT_RX

Definition at line 77 of file pattern.c.

#define RANGE_ABS_SLOT_RX   "[[:blank:]]*([.^$]|" RANGE_NUM_RX ")?[[:blank:]]*"

Definition at line 80 of file pattern.c.

#define RANGE_ABS_RX   "^" RANGE_ABS_SLOT_RX "-" RANGE_ABS_SLOT_RX

Definition at line 81 of file pattern.c.

#define RANGE_LT_RX   "^()[[:blank:]]*(<[[:blank:]]*" RANGE_NUM_RX ")[[:blank:]]*"

Definition at line 84 of file pattern.c.

#define RANGE_GT_RX   "^()[[:blank:]]*(>[[:blank:]]*" RANGE_NUM_RX ")[[:blank:]]*"

Definition at line 85 of file pattern.c.

#define RANGE_BARE_RX   "^[[:blank:]]*([.^$]|" RANGE_NUM_RX ")[[:blank:]]*"

Definition at line 88 of file pattern.c.

#define RANGE_RX_GROUPS   5

Definition at line 89 of file pattern.c.

#define KILO   1024

Definition at line 91 of file pattern.c.

#define MEGA   1048576

Definition at line 92 of file pattern.c.

#define HMSG (   h)    (((h)->msgno) + 1)

Definition at line 93 of file pattern.c.

#define CTX_MSGNO (   c)    (HMSG((c)->mailbox->hdrs[(c)->mailbox->v2r[(c)->menu->current]]))

Definition at line 94 of file pattern.c.

#define MUTT_MAXRANGE   -1

Definition at line 96 of file pattern.c.

#define MUTT_PDR_NONE   0x0000

Definition at line 99 of file pattern.c.

#define MUTT_PDR_MINUS   0x0001

Definition at line 100 of file pattern.c.

#define MUTT_PDR_PLUS   0x0002

Definition at line 101 of file pattern.c.

#define MUTT_PDR_WINDOW   0x0004

Definition at line 102 of file pattern.c.

#define MUTT_PDR_ABSOLUTE   0x0008

Definition at line 103 of file pattern.c.

#define MUTT_PDR_DONE   0x0010

Definition at line 104 of file pattern.c.

#define MUTT_PDR_ERROR   0x0100

Definition at line 105 of file pattern.c.

#define MUTT_PDR_ERRORDONE   (MUTT_PDR_ERROR | MUTT_PDR_DONE)

Definition at line 106 of file pattern.c.

#define RANGE_DOT   '.'

Definition at line 108 of file pattern.c.

#define RANGE_CIRCUM   '^'

Definition at line 109 of file pattern.c.

#define RANGE_DOLLAR   '$'

Definition at line 110 of file pattern.c.

#define RANGE_LT   '<'

Definition at line 111 of file pattern.c.

#define RANGE_GT   '>'

Definition at line 112 of file pattern.c.

Enumeration Type Documentation

Error codes for eat_range_by_regex()

Enumerator
RANGE_E_OK 

Range is valid.

RANGE_E_SYNTAX 

Range contains syntax error.

RANGE_E_CTX 

Range requires Context, but none available.

Definition at line 118 of file pattern.c.

119 {
120  RANGE_E_OK,
122  RANGE_E_CTX,
123 };
Range is valid.
Definition: pattern.c:120
Range contains syntax error.
Definition: pattern.c:121
Range requires Context, but none available.
Definition: pattern.c:122
enum RangeType

Type of range.

Enumerator
RANGE_K_REL 

Relative range.

RANGE_K_ABS 

Absolute range.

RANGE_K_LT 

Less-than range.

RANGE_K_GT 

Greater-than range.

RANGE_K_BARE 

Single symbol.

RANGE_K_INVALID 

Range is invalid.

Definition at line 140 of file pattern.c.

141 {
142  RANGE_K_REL,
143  RANGE_K_ABS,
144  RANGE_K_LT,
145  RANGE_K_GT,
146  RANGE_K_BARE,
147  /* add new ones HERE */
149 };
Single symbol.
Definition: pattern.c:146
Greater-than range.
Definition: pattern.c:145
Range is invalid.
Definition: pattern.c:148
Absolute range.
Definition: pattern.c:143
Less-than range.
Definition: pattern.c:144
Relative range.
Definition: pattern.c:142
enum RangeSide

Which side of the range.

Enumerator
RANGE_S_LEFT 

Left side of range.

RANGE_S_RIGHT 

Right side of range.

Definition at line 154 of file pattern.c.

155 {
156  RANGE_S_LEFT,
157  RANGE_S_RIGHT,
158 };
Left side of range.
Definition: pattern.c:156
Right side of range.
Definition: pattern.c:157

Function Documentation

static bool eat_regex ( struct Pattern pat,
struct Buffer s,
struct Buffer err 
)
static

Parse a regex.

Parameters
patPattern to match
sString to parse
errBuffer for error messages
Return values
trueIf the pattern was read succesfully

Definition at line 197 of file pattern.c.

198 {
199  struct Buffer buf;
200  char errmsg[STRING];
201  int r;
202 
203  mutt_buffer_init(&buf);
204  char *pexpr = s->dptr;
205  if (mutt_extract_token(&buf, s, MUTT_TOKEN_PATTERN | MUTT_TOKEN_COMMENT) != 0 || !buf.data)
206  {
207  mutt_buffer_printf(err, _("Error in expression: %s"), pexpr);
208  FREE(&buf.data);
209  return false;
210  }
211  if (!*buf.data)
212  {
213  mutt_buffer_printf(err, "%s", _("Empty expression"));
214  FREE(&buf.data);
215  return false;
216  }
217 
218  if (pat->stringmatch)
219  {
220  pat->p.str = mutt_str_strdup(buf.data);
221  pat->ign_case = mutt_mb_is_lower(buf.data);
222  FREE(&buf.data);
223  }
224  else if (pat->groupmatch)
225  {
226  pat->p.g = mutt_pattern_group(buf.data);
227  FREE(&buf.data);
228  }
229  else
230  {
231  pat->p.regex = mutt_mem_malloc(sizeof(regex_t));
232  int flags = mutt_mb_is_lower(buf.data) ? REG_ICASE : 0;
233  r = REGCOMP(pat->p.regex, buf.data, REG_NEWLINE | REG_NOSUB | flags);
234  if (r != 0)
235  {
236  regerror(r, pat->p.regex, errmsg, sizeof(errmsg));
237  mutt_buffer_add_printf(err, "'%s': %s", buf.data, errmsg);
238  FREE(&buf.data);
239  FREE(&pat->p.regex);
240  return false;
241  }
242  FREE(&buf.data);
243  }
244 
245  return true;
246 }
struct Group * mutt_pattern_group(const char *k)
Match a pattern to a Group.
Definition: group.c:45
regex_t * regex
Definition: pattern.h:58
#define MUTT_TOKEN_COMMENT
don&#39;t reap comments
Definition: mutt.h:76
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, int flags)
Extract one token from a string.
Definition: init.c:2520
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:239
bool ign_case
ignore case for local stringmatch searches
Definition: pattern.h:51
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
struct Group * g
Definition: pattern.h:59
char * dptr
current read/write position
Definition: buffer.h:36
char * data
pointer to data
Definition: buffer.h:35
#define STRING
Definition: string2.h:35
union Pattern::@2 p
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
char * str
Definition: pattern.h:60
#define FREE(x)
Definition: memory.h:46
bool groupmatch
Definition: pattern.h:50
bool stringmatch
Definition: pattern.h:49
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:66
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition: mbyte.c:346
#define MUTT_TOKEN_PATTERN
!)|~ are terms (for patterns)
Definition: mutt.h:75
#define REGCOMP(X, Y, Z)
Compile a regular expression.
Definition: regex3.h:52

+ Here is the call graph for this function:

static const char* get_offset ( struct tm *  tm,
const char *  s,
int  sign 
)
static

Calculate a symbolic offset.

Parameters
tmStore the time here
sstring to parse
signSign of range, 1 for positive, -1 for negative
Return values
ptrNext char after parsed offset
  • Ny years
  • Nm months
  • Nw weeks
  • Nd days

Definition at line 260 of file pattern.c.

261 {
262  char *ps = NULL;
263  int offset = strtol(s, &ps, 0);
264  if ((sign < 0 && offset > 0) || (sign > 0 && offset < 0))
265  offset = -offset;
266 
267  switch (*ps)
268  {
269  case 'y':
270  tm->tm_year += offset;
271  break;
272  case 'm':
273  tm->tm_mon += offset;
274  break;
275  case 'w':
276  tm->tm_mday += 7 * offset;
277  break;
278  case 'd':
279  tm->tm_mday += offset;
280  break;
281  case 'H':
282  tm->tm_hour += offset;
283  break;
284  case 'M':
285  tm->tm_min += offset;
286  break;
287  case 'S':
288  tm->tm_sec += offset;
289  break;
290  default:
291  return s;
292  }
294  return ps + 1;
295 }
void mutt_date_normalize_time(struct tm *tm)
Fix the contents of a struct tm.
Definition: date.c:302

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static const char* get_date ( const char *  s,
struct tm *  t,
struct Buffer err 
)
static

Parse a (partial) date in dd/mm/yyyy format.

Parameters
sString to parse
tStore the time here
errBuffer for error messages
Return values
ptrFirst character after the date

This function parses a (partial) date separated by '/'. The month and year are optional and if the year is less than 70 it's assumed to be after 2000.

Examples:

  • "10" = 23 of this month, this year
  • "10/12" = 10 of December, this year
  • "10/12/04" = 10 of December, 2004
  • "10/12/2008" = 10 of December, 2008

Definition at line 313 of file pattern.c.

314 {
315  char *p = NULL;
316  time_t now = time(NULL);
317  struct tm *tm = localtime(&now);
318 
319  t->tm_mday = strtol(s, &p, 10);
320  if (t->tm_mday < 1 || t->tm_mday > 31)
321  {
322  mutt_buffer_printf(err, _("Invalid day of month: %s"), s);
323  return NULL;
324  }
325  if (*p != '/')
326  {
327  /* fill in today's month and year */
328  t->tm_mon = tm->tm_mon;
329  t->tm_year = tm->tm_year;
330  return p;
331  }
332  p++;
333  t->tm_mon = strtol(p, &p, 10) - 1;
334  if (t->tm_mon < 0 || t->tm_mon > 11)
335  {
336  mutt_buffer_printf(err, _("Invalid month: %s"), p);
337  return NULL;
338  }
339  if (*p != '/')
340  {
341  t->tm_year = tm->tm_year;
342  return p;
343  }
344  p++;
345  t->tm_year = strtol(p, &p, 10);
346  if (t->tm_year < 70) /* year 2000+ */
347  t->tm_year += 100;
348  else if (t->tm_year > 1900)
349  t->tm_year -= 1900;
350  return p;
351 }
#define _(a)
Definition: message.h:28
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static const char* parse_date_range ( const char *  pc,
struct tm *  min,
struct tm *  max,
bool  have_min,
struct tm *  base_min,
struct Buffer err 
)
static

Parse a date range.

Parameters
pcString to parse
minEarlier date
maxLater date
have_minDo we have a base minimum date?
base_minBase minimum date
errBuffer for error messages
Return values
ptrFirst character after the date

Definition at line 363 of file pattern.c.

365 {
366  int flag = MUTT_PDR_NONE;
367  while (*pc && ((flag & MUTT_PDR_DONE) == 0))
368  {
369  const char *pt = NULL;
370  char ch = *pc++;
371  SKIPWS(pc);
372  switch (ch)
373  {
374  case '-':
375  {
376  /* try a range of absolute date minus offset of Ndwmy */
377  pt = get_offset(min, pc, -1);
378  if (pc == pt)
379  {
380  if (flag == MUTT_PDR_NONE)
381  { /* nothing yet and no offset parsed => absolute date? */
382  if (!get_date(pc, max, err))
383  flag |= (MUTT_PDR_ABSOLUTE | MUTT_PDR_ERRORDONE); /* done bad */
384  else
385  {
386  /* reestablish initial base minimum if not specified */
387  if (!have_min)
388  memcpy(min, base_min, sizeof(struct tm));
389  flag |= (MUTT_PDR_ABSOLUTE | MUTT_PDR_DONE); /* done good */
390  }
391  }
392  else
393  flag |= MUTT_PDR_ERRORDONE;
394  }
395  else
396  {
397  pc = pt;
398  if (flag == MUTT_PDR_NONE && !have_min)
399  { /* the very first "-3d" without a previous absolute date */
400  max->tm_year = min->tm_year;
401  max->tm_mon = min->tm_mon;
402  max->tm_mday = min->tm_mday;
403  }
404  flag |= MUTT_PDR_MINUS;
405  }
406  }
407  break;
408  case '+':
409  { /* enlarge plus range */
410  pt = get_offset(max, pc, 1);
411  if (pc == pt)
412  flag |= MUTT_PDR_ERRORDONE;
413  else
414  {
415  pc = pt;
416  flag |= MUTT_PDR_PLUS;
417  }
418  }
419  break;
420  case '*':
421  { /* enlarge window in both directions */
422  pt = get_offset(min, pc, -1);
423  if (pc == pt)
424  flag |= MUTT_PDR_ERRORDONE;
425  else
426  {
427  pc = get_offset(max, pc, 1);
428  flag |= MUTT_PDR_WINDOW;
429  }
430  }
431  break;
432  default:
433  flag |= MUTT_PDR_ERRORDONE;
434  }
435  SKIPWS(pc);
436  }
437  if ((flag & MUTT_PDR_ERROR) && !(flag & MUTT_PDR_ABSOLUTE))
438  { /* get_date has its own error message, don't overwrite it here */
439  mutt_buffer_printf(err, _("Invalid relative date: %s"), pc - 1);
440  }
441  return (flag & MUTT_PDR_ERROR) ? NULL : pc;
442 }
#define MUTT_PDR_ABSOLUTE
Definition: pattern.c:103
#define MUTT_PDR_WINDOW
Definition: pattern.c:102
#define MUTT_PDR_NONE
Definition: pattern.c:99
#define MUTT_PDR_ERROR
Definition: pattern.c:105
#define _(a)
Definition: message.h:28
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200
static const char * get_date(const char *s, struct tm *t, struct Buffer *err)
Parse a (partial) date in dd/mm/yyyy format.
Definition: pattern.c:313
static const char * get_offset(struct tm *tm, const char *s, int sign)
Calculate a symbolic offset.
Definition: pattern.c:260
#define MUTT_PDR_PLUS
Definition: pattern.c:101
#define MUTT_PDR_MINUS
Definition: pattern.c:100
#define MUTT_PDR_ERRORDONE
Definition: pattern.c:106
#define MUTT_PDR_DONE
Definition: pattern.c:104
#define SKIPWS(c)
Definition: string2.h:49

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void adjust_date_range ( struct tm *  min,
struct tm *  max 
)
static

Put a date range in the correct order.

Parameters
[in,out]minEarlier date
[in,out]maxLater date

Definition at line 449 of file pattern.c.

450 {
451  if (min->tm_year > max->tm_year ||
452  (min->tm_year == max->tm_year && min->tm_mon > max->tm_mon) ||
453  (min->tm_year == max->tm_year && min->tm_mon == max->tm_mon && min->tm_mday > max->tm_mday))
454  {
455  int tmp;
456 
457  tmp = min->tm_year;
458  min->tm_year = max->tm_year;
459  max->tm_year = tmp;
460 
461  tmp = min->tm_mon;
462  min->tm_mon = max->tm_mon;
463  max->tm_mon = tmp;
464 
465  tmp = min->tm_mday;
466  min->tm_mday = max->tm_mday;
467  max->tm_mday = tmp;
468 
469  min->tm_hour = 0;
470  min->tm_min = 0;
471  min->tm_sec = 0;
472  max->tm_hour = 23;
473  max->tm_min = 59;
474  max->tm_sec = 59;
475  }
476 }

+ Here is the caller graph for this function:

static bool eat_date ( struct Pattern pat,
struct Buffer s,
struct Buffer err 
)
static

Parse a date pattern.

Parameters
patPattern to store the date in
sString to parse
errBuffer for error messages
Return values
trueIf the pattern was read succesfully

Definition at line 485 of file pattern.c.

486 {
487  struct Buffer buf;
488  struct tm min, max;
489  char *offset_type = NULL;
490 
491  mutt_buffer_init(&buf);
492  char *pexpr = s->dptr;
493  if ((mutt_extract_token(&buf, s, MUTT_TOKEN_COMMENT | MUTT_TOKEN_PATTERN) != 0) || !buf.data)
494  {
495  FREE(&buf.data);
496  mutt_buffer_printf(err, _("Error in expression: %s"), pexpr);
497  return false;
498  }
499  if (!*buf.data)
500  {
501  FREE(&buf.data);
502  mutt_buffer_printf(err, "%s", _("Empty expression"));
503  return false;
504  }
505 
506  memset(&min, 0, sizeof(min));
507  /* the `0' time is Jan 1, 1970 UTC, so in order to prevent a negative time
508  when doing timezone conversion, we use Jan 2, 1970 UTC as the base
509  here */
510  min.tm_mday = 2;
511  min.tm_year = 70;
512 
513  memset(&max, 0, sizeof(max));
514 
515  /* Arbitrary year in the future. Don't set this too high
516  or mutt_date_make_time() returns something larger than will
517  fit in a time_t on some systems */
518  max.tm_year = 130;
519  max.tm_mon = 11;
520  max.tm_mday = 31;
521  max.tm_hour = 23;
522  max.tm_min = 59;
523  max.tm_sec = 59;
524 
525  if (strchr("<>=", buf.data[0]))
526  {
527  /* offset from current time
528  <3d less than three days ago
529  >3d more than three days ago
530  =3d exactly three days ago */
531  time_t now = time(NULL);
532  struct tm *tm = localtime(&now);
533  int exact = 0;
534 
535  if (buf.data[0] == '<')
536  {
537  memcpy(&min, tm, sizeof(min));
538  tm = &min;
539  }
540  else
541  {
542  memcpy(&max, tm, sizeof(max));
543  tm = &max;
544 
545  if (buf.data[0] == '=')
546  exact++;
547  }
548 
549  /* Reset the HMS unless we are relative matching using one of those
550  * offsets. */
551  strtol(buf.data + 1, &offset_type, 0);
552  if (!(*offset_type && strchr("HMS", *offset_type)))
553  {
554  tm->tm_hour = 23;
555  tm->tm_min = 59;
556  tm->tm_sec = 59;
557  }
558 
559  /* force negative offset */
560  get_offset(tm, buf.data + 1, -1);
561 
562  if (exact)
563  {
564  /* start at the beginning of the day in question */
565  memcpy(&min, &max, sizeof(max));
566  min.tm_hour = 0;
567  min.tm_sec = 0;
568  min.tm_min = 0;
569  }
570  }
571  else
572  {
573  const char *pc = buf.data;
574 
575  bool have_min = false;
576  int until_now = false;
577  if (isdigit((unsigned char) *pc))
578  {
579  /* minimum date specified */
580  pc = get_date(pc, &min, err);
581  if (!pc)
582  {
583  FREE(&buf.data);
584  return false;
585  }
586  have_min = true;
587  SKIPWS(pc);
588  if (*pc == '-')
589  {
590  const char *pt = pc + 1;
591  SKIPWS(pt);
592  until_now = (*pt == '\0');
593  }
594  }
595 
596  if (!until_now)
597  { /* max date or relative range/window */
598 
599  struct tm base_min;
600 
601  if (!have_min)
602  { /* save base minimum and set current date, e.g. for "-3d+1d" */
603  time_t now = time(NULL);
604  struct tm *tm = localtime(&now);
605  memcpy(&base_min, &min, sizeof(base_min));
606  memcpy(&min, tm, sizeof(min));
607  min.tm_hour = 0;
608  min.tm_sec = 0;
609  min.tm_min = 0;
610  }
611 
612  /* preset max date for relative offsets,
613  if nothing follows we search for messages on a specific day */
614  max.tm_year = min.tm_year;
615  max.tm_mon = min.tm_mon;
616  max.tm_mday = min.tm_mday;
617 
618  if (!parse_date_range(pc, &min, &max, have_min, &base_min, err))
619  { /* bail out on any parsing error */
620  FREE(&buf.data);
621  return false;
622  }
623  }
624  }
625 
626  /* Since we allow two dates to be specified we'll have to adjust that. */
627  adjust_date_range(&min, &max);
628 
629  pat->min = mutt_date_make_time(&min, 1);
630  pat->max = mutt_date_make_time(&max, 1);
631 
632  FREE(&buf.data);
633 
634  return true;
635 }
static void adjust_date_range(struct tm *min, struct tm *max)
Put a date range in the correct order.
Definition: pattern.c:449
#define MUTT_TOKEN_COMMENT
don&#39;t reap comments
Definition: mutt.h:76
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200
static const char * get_date(const char *s, struct tm *t, struct Buffer *err)
Parse a (partial) date in dd/mm/yyyy format.
Definition: pattern.c:313
static const char * get_offset(struct tm *tm, const char *s, int sign)
Calculate a symbolic offset.
Definition: pattern.c:260
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, int flags)
Extract one token from a string.
Definition: init.c:2520
int min
Definition: pattern.h:53
time_t mutt_date_make_time(struct tm *t, int local)
Convert struct tm to time_t
Definition: date.c:237
char * dptr
current read/write position
Definition: buffer.h:36
#define FREE(x)
Definition: memory.h:46
int max
Definition: pattern.h:54
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:66
#define MUTT_TOKEN_PATTERN
!)|~ are terms (for patterns)
Definition: mutt.h:75
static const char * parse_date_range(const char *pc, struct tm *min, struct tm *max, bool have_min, struct tm *base_min, struct Buffer *err)
Parse a date range.
Definition: pattern.c:363
#define SKIPWS(c)
Definition: string2.h:49

+ Here is the call graph for this function:

static bool eat_range ( struct Pattern pat,
struct Buffer s,
struct Buffer err 
)
static

Parse a number range.

Parameters
patPattern to store the range in
sString to parse
errBuffer for error messages
Return values
trueIf the pattern was read succesfully

Definition at line 644 of file pattern.c.

645 {
646  char *tmp = NULL;
647  bool do_exclusive = false;
648  bool skip_quote = false;
649 
650  /* If simple_search is set to "~m %s", the range will have double quotes
651  * around it...
652  */
653  if (*s->dptr == '"')
654  {
655  s->dptr++;
656  skip_quote = true;
657  }
658  if (*s->dptr == '<')
659  do_exclusive = true;
660  if ((*s->dptr != '-') && (*s->dptr != '<'))
661  {
662  /* range minimum */
663  if (*s->dptr == '>')
664  {
665  pat->max = MUTT_MAXRANGE;
666  pat->min = strtol(s->dptr + 1, &tmp, 0) + 1; /* exclusive range */
667  }
668  else
669  pat->min = strtol(s->dptr, &tmp, 0);
670  if (toupper((unsigned char) *tmp) == 'K') /* is there a prefix? */
671  {
672  pat->min *= 1024;
673  tmp++;
674  }
675  else if (toupper((unsigned char) *tmp) == 'M')
676  {
677  pat->min *= 1048576;
678  tmp++;
679  }
680  if (*s->dptr == '>')
681  {
682  s->dptr = tmp;
683  return true;
684  }
685  if (*tmp != '-')
686  {
687  /* exact value */
688  pat->max = pat->min;
689  s->dptr = tmp;
690  return true;
691  }
692  tmp++;
693  }
694  else
695  {
696  s->dptr++;
697  tmp = s->dptr;
698  }
699 
700  if (isdigit((unsigned char) *tmp))
701  {
702  /* range maximum */
703  pat->max = strtol(tmp, &tmp, 0);
704  if (toupper((unsigned char) *tmp) == 'K')
705  {
706  pat->max *= 1024;
707  tmp++;
708  }
709  else if (toupper((unsigned char) *tmp) == 'M')
710  {
711  pat->max *= 1048576;
712  tmp++;
713  }
714  if (do_exclusive)
715  (pat->max)--;
716  }
717  else
718  pat->max = MUTT_MAXRANGE;
719 
720  if (skip_quote && *tmp == '"')
721  tmp++;
722 
723  SKIPWS(tmp);
724  s->dptr = tmp;
725  return true;
726 }
#define MUTT_MAXRANGE
Definition: pattern.c:96
int min
Definition: pattern.h:53
char * dptr
current read/write position
Definition: buffer.h:36
int max
Definition: pattern.h:54
#define SKIPWS(c)
Definition: string2.h:49
static int report_regerror ( int  regerr,
regex_t *  preg,
struct Buffer err 
)
static

Create a regex error message.

Parameters
regerrRegex error code
pregRegex pattern buffer
errBuffer for error messages
Return values
RANGE_E_SYNTAXAlways

Definition at line 735 of file pattern.c.

736 {
737  size_t ds = err->dsize;
738 
739  if (regerror(regerr, preg, err->data, ds) > ds)
740  mutt_debug(2, "warning: buffer too small for regerror\n");
741  /* The return value is fixed, exists only to shorten code at callsite */
742  return RANGE_E_SYNTAX;
743 }
Range contains syntax error.
Definition: pattern.c:121
size_t dsize
length of data
Definition: buffer.h:37
char * data
pointer to data
Definition: buffer.h:35
#define mutt_debug(LEVEL,...)
Definition: logging.h:85

+ Here is the caller graph for this function:

static bool is_context_available ( struct Buffer s,
regmatch_t  pmatch[],
int  kind,
struct Buffer err 
)
static

Do we need a Context for this Pattern?

Parameters
sString to check
pmatchRegex matches
kindRange type, e.g. RANGE_K_REL
errBuffer for error messages
Return values
falseIf context is required, but not available
trueOtherwise

Definition at line 754 of file pattern.c.

756 {
757  const char *context_req_chars[] = {
758  [RANGE_K_REL] = ".0123456789",
759  [RANGE_K_ABS] = ".",
760  [RANGE_K_LT] = "",
761  [RANGE_K_GT] = "",
762  [RANGE_K_BARE] = ".",
763  };
764 
765  /* First decide if we're going to need the context at all.
766  * Relative patterns need it iff they contain a dot or a number.
767  * Absolute patterns only need it if they contain a dot. */
768  char *context_loc = strpbrk(s->dptr + pmatch[0].rm_so, context_req_chars[kind]);
769  if (!context_loc || (context_loc >= &s->dptr[pmatch[0].rm_eo]))
770  return true;
771 
772  /* We need a current message. Do we actually have one? */
773  if (Context && Context->menu)
774  return true;
775 
776  /* Nope. */
777  mutt_buffer_strcpy(err, _("No current message"));
778  return false;
779 }
The "current" mailbox.
Definition: context.h:36
Single symbol.
Definition: pattern.c:146
#define _(a)
Definition: message.h:28
struct Menu * menu
needed for pattern compilation
Definition: context.h:46
Greater-than range.
Definition: pattern.c:145
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:316
char * dptr
current read/write position
Definition: buffer.h:36
Absolute range.
Definition: pattern.c:143
Less-than range.
Definition: pattern.c:144
Relative range.
Definition: pattern.c:142

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int scan_range_num ( struct Buffer s,
regmatch_t  pmatch[],
int  group,
int  kind 
)
static

Parse a number range.

Parameters
sString to parse
pmatchArray of regex matches
groupIndex of regex match to use
kindRange type, e.g. RANGE_K_REL
Return values
numParse number

Definition at line 789 of file pattern.c.

790 {
791  int num;
792  unsigned char c;
793 
794  num = (int) strtol(&s->dptr[pmatch[group].rm_so], NULL, 0);
795  c = (unsigned char) (s->dptr[pmatch[group].rm_eo - 1]);
796  if (toupper(c) == 'K')
797  num *= KILO;
798  else if (toupper(c) == 'M')
799  num *= MEGA;
800  switch (kind)
801  {
802  case RANGE_K_REL:
803  return num + CTX_MSGNO(Context);
804  case RANGE_K_LT:
805  return num - 1;
806  case RANGE_K_GT:
807  return num + 1;
808  default:
809  return num;
810  }
811 }
The "current" mailbox.
Definition: context.h:36
#define MEGA
Definition: pattern.c:92
#define KILO
Definition: pattern.c:91
Greater-than range.
Definition: pattern.c:145
char * dptr
current read/write position
Definition: buffer.h:36
#define CTX_MSGNO(c)
Definition: pattern.c:94
Less-than range.
Definition: pattern.c:144
Relative range.
Definition: pattern.c:142

+ Here is the caller graph for this function:

static int scan_range_slot ( struct Buffer s,
regmatch_t  pmatch[],
int  grp,
int  side,
int  kind 
)
static

Parse a range of message numbers.

Parameters
sString to parse
pmatchRegex matches
grpWhich regex match to use
sideWhich side of the range is this? RANGE_S_LEFT or RANGE_S_RIGHT
kindRange type, e.g. RANGE_K_REL
Return values
numIndex number for the message specified

Definition at line 822 of file pattern.c.

823 {
824  unsigned char c;
825 
826  /* This means the left or right subpattern was empty, e.g. ",." */
827  if ((pmatch[grp].rm_so == -1) || (pmatch[grp].rm_so == pmatch[grp].rm_eo))
828  {
829  if (side == RANGE_S_LEFT)
830  return 1;
831  else if (side == RANGE_S_RIGHT)
832  return Context->mailbox->msg_count;
833  }
834  /* We have something, so determine what */
835  c = (unsigned char) (s->dptr[pmatch[grp].rm_so]);
836  switch (c)
837  {
838  case RANGE_CIRCUM:
839  return 1;
840  case RANGE_DOLLAR:
841  return Context->mailbox->msg_count;
842  case RANGE_DOT:
843  return CTX_MSGNO(Context);
844  case RANGE_LT:
845  case RANGE_GT:
846  return scan_range_num(s, pmatch, grp + 1, kind);
847  default:
848  /* Only other possibility: a number */
849  return scan_range_num(s, pmatch, grp, kind);
850  }
851 }
The "current" mailbox.
Definition: context.h:36
int msg_count
total number of messages
Definition: mailbox.h:86
#define RANGE_LT
Definition: pattern.c:111
#define RANGE_DOLLAR
Definition: pattern.c:110
struct Mailbox * mailbox
Definition: context.h:50
static int scan_range_num(struct Buffer *s, regmatch_t pmatch[], int group, int kind)
Parse a number range.
Definition: pattern.c:789
Left side of range.
Definition: pattern.c:156
char * dptr
current read/write position
Definition: buffer.h:36
#define RANGE_GT
Definition: pattern.c:112
#define CTX_MSGNO(c)
Definition: pattern.c:94
#define RANGE_CIRCUM
Definition: pattern.c:109
#define RANGE_DOT
Definition: pattern.c:108
Right side of range.
Definition: pattern.c:157

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void order_range ( struct Pattern pat)
static

Put a range in order.

Parameters
patPattern to check

Definition at line 857 of file pattern.c.

858 {
859  int num;
860 
861  if (pat->min <= pat->max)
862  return;
863  num = pat->min;
864  pat->min = pat->max;
865  pat->max = num;
866 }
int min
Definition: pattern.h:53
int max
Definition: pattern.h:54

+ Here is the caller graph for this function:

static int eat_range_by_regex ( struct Pattern pat,
struct Buffer s,
int  kind,
struct Buffer err 
)
static

Parse a range given as a regex.

Parameters
patPattern to store the range in
sString to parse
kindRange type, e.g. RANGE_K_REL
errBuffer for error messages
Return values
numEatRangeError code, e.g. RANGE_E_OK

Definition at line 876 of file pattern.c.

878 {
879  int regerr;
880  regmatch_t pmatch[RANGE_RX_GROUPS];
881  struct RangeRegex *pspec = &range_regexes[kind];
882 
883  /* First time through, compile the big regex */
884  if (!pspec->ready)
885  {
886  regerr = regcomp(&pspec->cooked, pspec->raw, REG_EXTENDED);
887  if (regerr)
888  return report_regerror(regerr, &pspec->cooked, err);
889  pspec->ready = 1;
890  }
891 
892  /* Match the pattern buffer against the compiled regex.
893  * No match means syntax error. */
894  regerr = regexec(&pspec->cooked, s->dptr, RANGE_RX_GROUPS, pmatch, 0);
895  if (regerr)
896  return report_regerror(regerr, &pspec->cooked, err);
897 
898  if (!is_context_available(s, pmatch, kind, err))
899  return RANGE_E_CTX;
900 
901  /* Snarf the contents of the two sides of the range. */
902  pat->min = scan_range_slot(s, pmatch, pspec->lgrp, RANGE_S_LEFT, kind);
903  pat->max = scan_range_slot(s, pmatch, pspec->rgrp, RANGE_S_RIGHT, kind);
904  mutt_debug(1, "pat->min=%d pat->max=%d\n", pat->min, pat->max);
905 
906  /* Special case for a bare 0. */
907  if ((kind == RANGE_K_BARE) && (pat->min == 0) && (pat->max == 0))
908  {
909  if (!Context->menu)
910  {
911  mutt_buffer_strcpy(err, _("No current message"));
912  return RANGE_E_CTX;
913  }
914  pat->max = CTX_MSGNO(Context);
915  pat->min = pat->max;
916  }
917 
918  /* Since we don't enforce order, we must swap bounds if they're backward */
919  order_range(pat);
920 
921  /* Slide pointer past the entire match. */
922  s->dptr += pmatch[0].rm_eo;
923  return RANGE_E_OK;
924 }
The "current" mailbox.
Definition: context.h:36
regex_t cooked
compiled form
Definition: pattern.c:134
Single symbol.
Definition: pattern.c:146
Range is valid.
Definition: pattern.c:120
#define _(a)
Definition: message.h:28
Range requires Context, but none available.
Definition: pattern.c:122
struct Menu * menu
needed for pattern compilation
Definition: context.h:46
int ready
compiled yet?
Definition: pattern.c:133
int min
Definition: pattern.h:53
Left side of range.
Definition: pattern.c:156
Regular expression representing a range.
Definition: pattern.c:128
#define RANGE_RX_GROUPS
Definition: pattern.c:89
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:316
static struct RangeRegex range_regexes[]
Set of Regexes for various range types.
Definition: pattern.c:177
char * dptr
current read/write position
Definition: buffer.h:36
const char * raw
regex as string
Definition: pattern.c:130
#define CTX_MSGNO(c)
Definition: pattern.c:94
static void order_range(struct Pattern *pat)
Put a range in order.
Definition: pattern.c:857
static int scan_range_slot(struct Buffer *s, regmatch_t pmatch[], int grp, int side, int kind)
Parse a range of message numbers.
Definition: pattern.c:822
int max
Definition: pattern.h:54
static int report_regerror(int regerr, regex_t *preg, struct Buffer *err)
Create a regex error message.
Definition: pattern.c:735
int lgrp
paren group matching the left side
Definition: pattern.c:131
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
int rgrp
paren group matching the right side
Definition: pattern.c:132
static bool is_context_available(struct Buffer *s, regmatch_t pmatch[], int kind, struct Buffer *err)
Do we need a Context for this Pattern?
Definition: pattern.c:754
Right side of range.
Definition: pattern.c:157

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool eat_message_range ( struct Pattern pat,
struct Buffer s,
struct Buffer err 
)
static

Parse a range of message numbers.

Parameters
patPattern to store the range in
sString to parse
errBuffer for error messages
Return values
trueIf the pattern was read succesfully

Definition at line 933 of file pattern.c.

934 {
935  bool skip_quote = false;
936 
937  /* We need a Context for pretty much anything. */
938  if (!Context)
939  {
940  mutt_buffer_strcpy(err, _("No Context"));
941  return false;
942  }
943 
944  /* If simple_search is set to "~m %s", the range will have double quotes
945  * around it...
946  */
947  if (*s->dptr == '"')
948  {
949  s->dptr++;
950  skip_quote = true;
951  }
952 
953  for (int i_kind = 0; i_kind != RANGE_K_INVALID; ++i_kind)
954  {
955  switch (eat_range_by_regex(pat, s, i_kind, err))
956  {
957  case RANGE_E_CTX:
958  /* This means it matched syntactically but lacked context.
959  * No point in continuing. */
960  break;
961  case RANGE_E_SYNTAX:
962  /* Try another syntax, then */
963  continue;
964  case RANGE_E_OK:
965  if (skip_quote && (*s->dptr == '"'))
966  s->dptr++;
967  SKIPWS(s->dptr);
968  return true;
969  }
970  }
971  return false;
972 }
The "current" mailbox.
Definition: context.h:36
Range is valid.
Definition: pattern.c:120
Range contains syntax error.
Definition: pattern.c:121
#define _(a)
Definition: message.h:28
Range requires Context, but none available.
Definition: pattern.c:122
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:316
char * dptr
current read/write position
Definition: buffer.h:36
Range is invalid.
Definition: pattern.c:148
static int eat_range_by_regex(struct Pattern *pat, struct Buffer *s, int kind, struct Buffer *err)
Parse a range given as a regex.
Definition: pattern.c:876
#define SKIPWS(c)
Definition: string2.h:49

+ Here is the call graph for this function:

static int patmatch ( const struct Pattern pat,
const char *  buf 
)
static

Compare a string to a Pattern.

Parameters
patPattern to use
bufString to compare
Return values
0Match
1No match

Definition at line 981 of file pattern.c.

982 {
983  if (pat->stringmatch)
984  return pat->ign_case ? !strcasestr(buf, pat->p.str) : !strstr(buf, pat->p.str);
985  else if (pat->groupmatch)
986  return !mutt_group_match(pat->p.g, buf);
987  else
988  return regexec(pat->p.regex, buf, 0, NULL, 0);
989 }
regex_t * regex
Definition: pattern.h:58
bool mutt_group_match(struct Group *g, const char *s)
Does a string match an entry in a Group?
Definition: group.c:289
bool ign_case
ignore case for local stringmatch searches
Definition: pattern.h:51
struct Group * g
Definition: pattern.h:59
union Pattern::@2 p
char * str
Definition: pattern.h:60
bool groupmatch
Definition: pattern.h:50
bool stringmatch
Definition: pattern.h:49

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool msg_search ( struct Mailbox m,
struct Pattern pat,
int  msgno 
)
static

Search an email.

Parameters
mMailbox
patPattern to find
msgnoMessage to search
Return values
truePattern found
falseError or pattern not found

Definition at line 999 of file pattern.c.

1000 {
1001  bool match = false;
1002  struct Message *msg = mx_msg_open(m, msgno);
1003  if (!msg)
1004  {
1005  return match;
1006  }
1007 
1008  FILE *fp = NULL;
1009  long lng = 0;
1010  struct Email *e = m->hdrs[msgno];
1011 #ifdef USE_FMEMOPEN
1012  char *temp = NULL;
1013  size_t tempsize;
1014 #else
1015  struct stat st;
1016 #endif
1017 
1018  if (ThoroughSearch)
1019  {
1020  /* decode the header / body */
1021  struct State s = { 0 };
1022  s.fpin = msg->fp;
1023  s.flags = MUTT_CHARCONV;
1024 #ifdef USE_FMEMOPEN
1025  s.fpout = open_memstream(&temp, &tempsize);
1026  if (!s.fpout)
1027  {
1028  mutt_perror(_("Error opening 'memory stream'"));
1029  return false;
1030  }
1031 #else
1032  s.fpout = mutt_file_mkstemp();
1033  if (!s.fpout)
1034  {
1035  mutt_perror(_("Can't create temporary file"));
1036  return false;
1037  }
1038 #endif
1039 
1040  if (pat->op != MUTT_BODY)
1041  mutt_copy_header(msg->fp, e, s.fpout, CH_FROM | CH_DECODE, NULL);
1042 
1043  if (pat->op != MUTT_HEADER)
1044  {
1046 
1047  if ((WithCrypto != 0) && (e->security & ENCRYPT) && !crypt_valid_passphrase(e->security))
1048  {
1049  mx_msg_close(m, &msg);
1050  if (s.fpout)
1051  {
1052  mutt_file_fclose(&s.fpout);
1053 #ifdef USE_FMEMOPEN
1054  FREE(&temp);
1055 #endif
1056  }
1057  return false;
1058  }
1059 
1060  fseeko(msg->fp, e->offset, SEEK_SET);
1061  mutt_body_handler(e->content, &s);
1062  }
1063 
1064 #ifdef USE_FMEMOPEN
1065  fclose(s.fpout);
1066  lng = tempsize;
1067 
1068  if (tempsize)
1069  {
1070  fp = fmemopen(temp, tempsize, "r");
1071  if (!fp)
1072  {
1073  mutt_perror(_("Error re-opening 'memory stream'"));
1074  return false;
1075  }
1076  }
1077  else
1078  { /* fmemopen cannot handle empty buffers */
1079  fp = mutt_file_fopen("/dev/null", "r");
1080  if (!fp)
1081  {
1082  mutt_perror(_("Error opening /dev/null"));
1083  return false;
1084  }
1085  }
1086 #else
1087  fp = s.fpout;
1088  fflush(fp);
1089  fseek(fp, 0, SEEK_SET);
1090  fstat(fileno(fp), &st);
1091  lng = (long) st.st_size;
1092 #endif
1093  }
1094  else
1095  {
1096  /* raw header / body */
1097  fp = msg->fp;
1098  if (pat->op != MUTT_BODY)
1099  {
1100  fseeko(fp, e->offset, SEEK_SET);
1101  lng = e->content->offset - e->offset;
1102  }
1103  if (pat->op != MUTT_HEADER)
1104  {
1105  if (pat->op == MUTT_BODY)
1106  fseeko(fp, e->content->offset, SEEK_SET);
1107  lng += e->content->length;
1108  }
1109  }
1110 
1111  size_t blen = STRING;
1112  char *buf = mutt_mem_malloc(blen);
1113 
1114  /* search the file "fp" */
1115  while (lng > 0)
1116  {
1117  if (pat->op == MUTT_HEADER)
1118  {
1119  buf = mutt_rfc822_read_line(fp, buf, &blen);
1120  if (*buf == '\0')
1121  break;
1122  }
1123  else if (!fgets(buf, blen - 1, fp))
1124  break; /* don't loop forever */
1125  if (patmatch(pat, buf) == 0)
1126  {
1127  match = true;
1128  break;
1129  }
1130  lng -= mutt_str_strlen(buf);
1131  }
1132 
1133  FREE(&buf);
1134 
1135  mx_msg_close(m, &msg);
1136 
1137  if (ThoroughSearch)
1138  {
1139  mutt_file_fclose(&fp);
1140 #ifdef USE_FMEMOPEN
1141  if (tempsize)
1142  FREE(&temp);
1143 #endif
1144  }
1145 
1146  return match;
1147 }
static int patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:981
The envelope/body of an email.
Definition: email.h:35
#define mutt_perror(...)
Definition: logging.h:89
int mutt_copy_header(FILE *in, struct Email *e, FILE *out, int flags, const char *prefix)
Copy Email header.
Definition: copy.c:406
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:44
unsigned int security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:37
struct Body * content
list of MIME parts
Definition: email.h:92
LOFF_T offset
offset where the actual data begins
Definition: body.h:45
#define CH_FROM
retain the "From " message separator?
Definition: copy.h:51
#define _(a)
Definition: message.h:28
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:663
struct Email ** hdrs
Definition: mailbox.h:93
FILE * fpout
Definition: state.h:34
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1187
int flags
Definition: state.h:36
void mutt_parse_mime_message(struct Mailbox *m, struct Email *cur)
Parse a MIME email.
Definition: mutt_parse.c:50
#define ENCRYPT
Definition: ncrypt.h:119
char * mutt_rfc822_read_line(FILE *f, char *line, size_t *linelen)
Read a header line from a file.
Definition: parse.c:900
A local copy of an email.
Definition: mx.h:81
LOFF_T length
length (in bytes) of attachment
Definition: body.h:46
Pattern matches email&#39;s header.
Definition: mutt.h:148
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
#define CH_DECODE
do RFC1522 decoding?
Definition: copy.h:49
#define mutt_file_mkstemp()
Definition: file.h:103
short op
Definition: pattern.h:46
FILE * fpin
Definition: state.h:33
LOFF_T offset
where in the stream does this message begin?
Definition: email.h:85
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:548
#define STRING
Definition: string2.h:35
int mutt_file_fclose(FILE **f)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
bool ThoroughSearch
Config: Decode headers and messages before searching them.
Definition: pattern.c:71
FILE * fp
pointer to the message data
Definition: mx.h:83
#define FREE(x)
Definition: memory.h:46
int crypt_valid_passphrase(int flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:144
Keep track when processing files.
Definition: state.h:31
Pattern matches email&#39;s body.
Definition: mutt.h:147
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1502
#define WithCrypto
Definition: ncrypt.h:154
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1139
int msgno
number displayed to the user
Definition: email.h:88

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static const struct PatternFlags* lookup_tag ( char  tag)
static

Lookup a pattern modifier.

Parameters
tagLetter, e.g. 'b' for pattern '~b'
Return values
ptrPattern data

Definition at line 1212 of file pattern.c.

1213 {
1214  for (int i = 0; Flags[i].tag; i++)
1215  if (Flags[i].tag == tag)
1216  return &Flags[i];
1217  return NULL;
1218 }
int tag
character used to represent this op
Definition: pattern.c:165
static const struct PatternFlags Flags[]
Lookup table for all patterns.
Definition: pattern.c:1153

+ Here is the caller graph for this function:

static char* find_matching_paren ( char *  s)
static

Find the matching parenthesis.

Parameters
sstring to search
Return values
ptrMatching close parenthesis
ptrEnd of string NUL, if not found

Definition at line 1226 of file pattern.c.

1227 {
1228  int level = 1;
1229 
1230  for (; *s; s++)
1231  {
1232  if (*s == '(')
1233  level++;
1234  else if (*s == ')')
1235  {
1236  level--;
1237  if (!level)
1238  break;
1239  }
1240  }
1241  return s;
1242 }

+ Here is the caller graph for this function:

void mutt_pattern_free ( struct Pattern **  pat)

Free a Pattern.

Parameters
patPattern to free

Definition at line 1248 of file pattern.c.

1249 {
1250  struct Pattern *tmp = NULL;
1251 
1252  while (*pat)
1253  {
1254  tmp = *pat;
1255  *pat = (*pat)->next;
1256 
1257  if (tmp->stringmatch)
1258  FREE(&tmp->p.str);
1259  else if (tmp->groupmatch)
1260  tmp->p.g = NULL;
1261  else if (tmp->p.regex)
1262  {
1263  regfree(tmp->p.regex);
1264  FREE(&tmp->p.regex);
1265  }
1266 
1267  if (tmp->child)
1268  mutt_pattern_free(&tmp->child);
1269  FREE(&tmp);
1270  }
1271 }
regex_t * regex
Definition: pattern.h:58
void mutt_pattern_free(struct Pattern **pat)
Free a Pattern.
Definition: pattern.c:1248
A simple (non-regex) pattern.
Definition: pattern.h:44
struct Pattern * next
Definition: pattern.h:55
struct Group * g
Definition: pattern.h:59
struct Pattern * child
arguments to logical op
Definition: pattern.h:56
union Pattern::@2 p
char * str
Definition: pattern.h:60
#define FREE(x)
Definition: memory.h:46
bool groupmatch
Definition: pattern.h:50
bool stringmatch
Definition: pattern.h:49

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct Pattern* mutt_pattern_new ( void  )

Create a new Pattern.

Return values
ptrNew Pattern

Definition at line 1277 of file pattern.c.

1278 {
1279  return mutt_mem_calloc(1, sizeof(struct Pattern));
1280 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
A simple (non-regex) pattern.
Definition: pattern.h:44

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct Pattern* mutt_pattern_comp ( char *  s,
int  flags,
struct Buffer err 
)

Create a Pattern.

Parameters
sPattern string
flagsFlags, e.g. MUTT_FULL_MSG
errBuffer for error messages
Return values
ptrNewly allocated Pattern

Definition at line 1289 of file pattern.c.

1290 {
1291  struct Pattern *curlist = NULL;
1292  struct Pattern *tmp = NULL, *tmp2 = NULL;
1293  struct Pattern *last = NULL;
1294  bool not = false;
1295  bool alladdr = false;
1296  bool or = false;
1297  bool implicit = true; /* used to detect logical AND operator */
1298  bool isalias = false;
1299  short thread_op;
1300  const struct PatternFlags *entry = NULL;
1301  char *p = NULL;
1302  char *buf = NULL;
1303  struct Buffer ps;
1304 
1305  mutt_buffer_init(&ps);
1306  ps.dptr = s;
1307  ps.dsize = mutt_str_strlen(s);
1308 
1309  while (*ps.dptr)
1310  {
1311  SKIPWS(ps.dptr);
1312  switch (*ps.dptr)
1313  {
1314  case '^':
1315  ps.dptr++;
1316  alladdr = !alladdr;
1317  break;
1318  case '!':
1319  ps.dptr++;
1320  not = !not;
1321  break;
1322  case '@':
1323  ps.dptr++;
1324  isalias = !isalias;
1325  break;
1326  case '|':
1327  if (! or)
1328  {
1329  if (!curlist)
1330  {
1331  mutt_buffer_printf(err, _("error in pattern at: %s"), ps.dptr);
1332  return NULL;
1333  }
1334  if (curlist->next)
1335  {
1336  /* A & B | C == (A & B) | C */
1337  tmp = mutt_pattern_new();
1338  tmp->op = MUTT_AND;
1339  tmp->child = curlist;
1340 
1341  curlist = tmp;
1342  last = curlist;
1343  }
1344 
1345  or = true;
1346  }
1347  ps.dptr++;
1348  implicit = false;
1349  not = false;
1350  alladdr = false;
1351  isalias = false;
1352  break;
1353  case '%':
1354  case '=':
1355  case '~':
1356  if (!*(ps.dptr + 1))
1357  {
1358  mutt_buffer_printf(err, _("missing pattern: %s"), ps.dptr);
1359  mutt_pattern_free(&curlist);
1360  return NULL;
1361  }
1362  thread_op = 0;
1363  if (*(ps.dptr + 1) == '(')
1364  thread_op = MUTT_THREAD;
1365  else if ((*(ps.dptr + 1) == '<') && (*(ps.dptr + 2) == '('))
1366  thread_op = MUTT_PARENT;
1367  else if ((*(ps.dptr + 1) == '>') && (*(ps.dptr + 2) == '('))
1368  thread_op = MUTT_CHILDREN;
1369  if (thread_op)
1370  {
1371  ps.dptr++; /* skip ~ */
1372  if (thread_op == MUTT_PARENT || thread_op == MUTT_CHILDREN)
1373  ps.dptr++;
1374  p = find_matching_paren(ps.dptr + 1);
1375  if (*p != ')')
1376  {
1377  mutt_buffer_printf(err, _("mismatched brackets: %s"), ps.dptr);
1378  mutt_pattern_free(&curlist);
1379  return NULL;
1380  }
1381  tmp = mutt_pattern_new();
1382  tmp->op = thread_op;
1383  if (last)
1384  last->next = tmp;
1385  else
1386  curlist = tmp;
1387  last = tmp;
1388  tmp->not ^= not;
1389  tmp->alladdr |= alladdr;
1390  tmp->isalias |= isalias;
1391  not = false;
1392  alladdr = false;
1393  isalias = false;
1394  /* compile the sub-expression */
1395  buf = mutt_str_substr_dup(ps.dptr + 1, p);
1396  tmp2 = mutt_pattern_comp(buf, flags, err);
1397  if (!tmp2)
1398  {
1399  FREE(&buf);
1400  mutt_pattern_free(&curlist);
1401  return NULL;
1402  }
1403  FREE(&buf);
1404  tmp->child = tmp2;
1405  ps.dptr = p + 1; /* restore location */
1406  break;
1407  }
1408  if (implicit && or)
1409  {
1410  /* A | B & C == (A | B) & C */
1411  tmp = mutt_pattern_new();
1412  tmp->op = MUTT_OR;
1413  tmp->child = curlist;
1414  curlist = tmp;
1415  last = tmp;
1416  or = false;
1417  }
1418 
1419  tmp = mutt_pattern_new();
1420  tmp->not = not;
1421  tmp->alladdr = alladdr;
1422  tmp->isalias = isalias;
1423  tmp->stringmatch = (*ps.dptr == '=');
1424  tmp->groupmatch = (*ps.dptr == '%');
1425  not = false;
1426  alladdr = false;
1427  isalias = false;
1428 
1429  if (last)
1430  last->next = tmp;
1431  else
1432  curlist = tmp;
1433  last = tmp;
1434 
1435  ps.dptr++; /* move past the ~ */
1436  entry = lookup_tag(*ps.dptr);
1437  if (!entry)
1438  {
1439  mutt_buffer_printf(err, _("%c: invalid pattern modifier"), *ps.dptr);
1440  mutt_pattern_free(&curlist);
1441  return NULL;
1442  }
1443  if (entry->class && (flags & entry->class) == 0)
1444  {
1445  mutt_buffer_printf(err, _("%c: not supported in this mode"), *ps.dptr);
1446  mutt_pattern_free(&curlist);
1447  return NULL;
1448  }
1449  tmp->op = entry->op;
1450 
1451  ps.dptr++; /* eat the operator and any optional whitespace */
1452  SKIPWS(ps.dptr);
1453 
1454  if (entry->eat_arg)
1455  {
1456  if (!*ps.dptr)
1457  {
1458  mutt_buffer_printf(err, "%s", _("missing parameter"));
1459  mutt_pattern_free(&curlist);
1460  return NULL;
1461  }
1462  if (!entry->eat_arg(tmp, &ps, err))
1463  {
1464  mutt_pattern_free(&curlist);
1465  return NULL;
1466  }
1467  }
1468  implicit = true;
1469  break;
1470  case '(':
1471  p = find_matching_paren(ps.dptr + 1);
1472  if (*p != ')')
1473  {
1474  mutt_buffer_printf(err, _("mismatched parenthesis: %s"), ps.dptr);
1475  mutt_pattern_free(&curlist);
1476  return NULL;
1477  }
1478  /* compile the sub-expression */
1479  buf = mutt_str_substr_dup(ps.dptr + 1, p);
1480  tmp = mutt_pattern_comp(buf, flags, err);
1481  if (!tmp)
1482  {
1483  FREE(&buf);
1484  mutt_pattern_free(&curlist);
1485  return NULL;
1486  }
1487  FREE(&buf);
1488  if (last)
1489  last->next = tmp;
1490  else
1491  curlist = tmp;
1492  last = tmp;
1493  tmp->not ^= not;
1494  tmp->alladdr |= alladdr;
1495  tmp->isalias |= isalias;
1496  not = false;
1497  alladdr = false;
1498  isalias = false;
1499  ps.dptr = p + 1; /* restore location */
1500  break;
1501  default:
1502  mutt_buffer_printf(err, _("error in pattern at: %s"), ps.dptr);
1503  mutt_pattern_free(&curlist);
1504  return NULL;
1505  }
1506  }
1507  if (!curlist)
1508  {
1509  mutt_buffer_strcpy(err, _("empty pattern"));
1510  return NULL;
1511  }
1512  if (curlist->next)
1513  {
1514  tmp = mutt_pattern_new();
1515  tmp->op = or ? MUTT_OR : MUTT_AND;
1516  tmp->child = curlist;
1517  curlist = tmp;
1518  }
1519  return curlist;
1520 }
bool not
Definition: pattern.h:47
String manipulation buffer.
Definition: buffer.h:33
Either pattern can match.
Definition: mutt.h:132
#define _(a)
Definition: message.h:28
void mutt_pattern_free(struct Pattern **pat)
Free a Pattern.
Definition: pattern.c:1248
static char * find_matching_paren(char *s)
Find the matching parenthesis.
Definition: pattern.c:1226
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:663
Pattern matches a child email.
Definition: mutt.h:135
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200
A simple (non-regex) pattern.
Definition: pattern.h:44
Both patterns must match.
Definition: mutt.h:131
int op
operation to perform
Definition: pattern.c:166
struct Pattern * mutt_pattern_new(void)
Create a new Pattern.
Definition: pattern.c:1277
struct Pattern * next
Definition: pattern.h:55
static const struct PatternFlags * lookup_tag(char tag)
Lookup a pattern modifier.
Definition: pattern.c:1212
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:316
struct Pattern * child
arguments to logical op
Definition: pattern.h:56
int class
Pattern class, e.g.
Definition: pattern.c:167
short op
Definition: pattern.h:46
struct Pattern * mutt_pattern_comp(char *s, int flags, struct Buffer *err)
Create a Pattern.
Definition: pattern.c:1289
bool isalias
Definition: pattern.h:52
Pattern matches parent.
Definition: mutt.h:134
bool(* eat_arg)(struct Pattern *, struct Buffer *, struct Buffer *)
Callback function to parse the argument.
Definition: pattern.c:168
#define FREE(x)
Definition: memory.h:46
bool groupmatch
Definition: pattern.h:50
bool stringmatch
Definition: pattern.h:49
bool alladdr
Definition: pattern.h:48
Mapping between user character and internal constant.
Definition: pattern.c:163
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:66
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:576
Pattern matches email thread.
Definition: mutt.h:133
#define SKIPWS(c)
Definition: string2.h:49

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool perform_and ( struct Pattern pat,
enum PatternExecFlag  flags,
struct Mailbox m,
struct Email e,
struct PatternCache cache 
)
static

Perform a logical AND on a set of Patterns.

Parameters
patPatterns to test
flagsOptional flags, e.g. MUTT_MATCH_FULL_ADDRESS
mMailbox
eEmail
cacheCached Patterns
Return values
trueIf ALL of the Patterns evaluates to true

Definition at line 1531 of file pattern.c.

1533 {
1534  for (; pat; pat = pat->next)
1535  if (mutt_pattern_exec(pat, flags, m, e, cache) <= 0)
1536  return false;
1537  return true;
1538 }
struct Pattern * next
Definition: pattern.h:55
int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1837

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int perform_or ( struct Pattern pat,
enum PatternExecFlag  flags,
struct Mailbox m,
struct Email e,
struct PatternCache cache 
)
static

Perform a logical OR on a set of Patterns.

Parameters
patPatterns to test
flagsOptional flags, e.g. MUTT_MATCH_FULL_ADDRESS
mMailbox
eEmail
cacheCached Patterns
Return values
trueIf ONE (or more) of the Patterns evaluates to true

Definition at line 1549 of file pattern.c.

1551 {
1552  for (; pat; pat = pat->next)
1553  if (mutt_pattern_exec(pat, flags, m, e, cache) > 0)
1554  return true;
1555  return false;
1556 }
struct Pattern * next
Definition: pattern.h:55
int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1837

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int match_addrlist ( struct Pattern pat,
bool  match_personal,
int  n,
  ... 
)
static

Match a Pattern against and Address list.

Parameters
patPattern to find
match_personalIf true, also match the pattern against the real name
nNumber of Addresses supplied
...Variable number of Addresses
Return values
trueOne Address matches (alladdr is false)
trueAll the Addresses match (alladdr is true)

Definition at line 1567 of file pattern.c.

1568 {
1569  va_list ap;
1570 
1571  va_start(ap, n);
1572  for (; n; n--)
1573  {
1574  for (struct Address *a = va_arg(ap, struct Address *); a; a = a->next)
1575  {
1576  if (pat->alladdr ^ ((!pat->isalias || mutt_alias_reverse_lookup(a)) &&
1577  ((a->mailbox && !patmatch(pat, a->mailbox)) ||
1578  (match_personal && a->personal && !patmatch(pat, a->personal)))))
1579  {
1580  va_end(ap);
1581  return !pat->alladdr; /* Found match, or non-match if alladdr */
1582  }
1583  }
1584  }
1585  va_end(ap);
1586  return pat->alladdr; /* No matches, or all matches if alladdr */
1587 }
static int patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:981
struct Address * mutt_alias_reverse_lookup(struct Address *a)
Does the user have an alias for the given address.
Definition: alias.c:535
An email address.
Definition: address.h:32
bool isalias
Definition: pattern.h:52
bool alladdr
Definition: pattern.h:48
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool match_reference ( struct Pattern pat,
struct ListHead *  refs 
)
static

Match references against a Pattern.

Parameters
patPattern to match
refsList of References
Return values
trueOne of the references matches

Definition at line 1595 of file pattern.c.

1596 {
1597  struct ListNode *np = NULL;
1598  STAILQ_FOREACH(np, refs, entries)
1599  {
1600  if (patmatch(pat, np->data) == 0)
1601  return true;
1602  }
1603  return false;
1604 }
static int patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:981
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:350
char * data
Definition: list.h:35
A List node for strings.
Definition: list.h:33

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_is_list_recipient ( bool  alladdr,
struct Address a1,
struct Address a2 
)

Matches subscribed mailing lists.

Parameters
alladdrIf true, ALL Addresses must be on the subscribed list
a1First Address list
a2Second Address list
Return values
trueOne Address is subscribed (alladdr is false)
trueAll the Addresses are subscribed (alladdr is true)

Definition at line 1614 of file pattern.c.

1615 {
1616  for (; a1; a1 = a1->next)
1617  if (alladdr ^ mutt_is_subscribed_list(a1))
1618  return !alladdr;
1619  for (; a2; a2 = a2->next)
1620  if (alladdr ^ mutt_is_subscribed_list(a2))
1621  return !alladdr;
1622  return alladdr;
1623 }
bool mutt_is_subscribed_list(struct Address *addr)
Is this the email address of a user-subscribed mailing list?
Definition: hdrline.c:110
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_is_list_cc ( int  alladdr,
struct Address a1,
struct Address a2 
)

Matches known mailing lists.

Parameters
alladdrIf true, ALL Addresses must be mailing lists
a1First Address list
a2Second Address list
Return values
trueOne Address is a mailing list (alladdr is false)
trueAll the Addresses are mailing lists (alladdr is true)

The function name may seem a little bit misleading: It checks all recipients in To and Cc for known mailing lists, subscribed or not.

Definition at line 1636 of file pattern.c.

1637 {
1638  for (; a1; a1 = a1->next)
1639  if (alladdr ^ mutt_is_mail_list(a1))
1640  return !alladdr;
1641  for (; a2; a2 = a2->next)
1642  if (alladdr ^ mutt_is_mail_list(a2))
1643  return !alladdr;
1644  return alladdr;
1645 }
bool mutt_is_mail_list(struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:98
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int match_user ( int  alladdr,
struct Address a1,
struct Address a2 
)
static

Matches the user's email Address.

Parameters
alladdrIf true, ALL Addresses must refer to the user
a1First Address list
a2Second Address list
Return values
trueOne Address refers to the user (alladdr is false)
trueAll the Addresses refer to the user (alladdr is true)

Definition at line 1655 of file pattern.c.

1656 {
1657  for (; a1; a1 = a1->next)
1658  if (alladdr ^ mutt_addr_is_user(a1))
1659  return !alladdr;
1660  for (; a2; a2 = a2->next)
1661  if (alladdr ^ mutt_addr_is_user(a2))
1662  return !alladdr;
1663  return alladdr;
1664 }
bool mutt_addr_is_user(struct Address *addr)
Does the address belong to the user.
Definition: alias.c:676
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int match_threadcomplete ( struct Pattern pat,
enum PatternExecFlag  flags,
struct Mailbox m,
struct MuttThread t,
int  left,
int  up,
int  right,
int  down 
)
static

Match a Pattern against an email thread.

Parameters
patPattern to match
flagsFlags, e.g. MUTT_MATCH_FULL_ADDRESS
mMailbox
tEmail thread
leftNavigate to the previous email
upNavigate to the email's parent
rightNavigate to the next email
downNavigate to the email's children
Return values
1Success, match found
0No match

Definition at line 1679 of file pattern.c.

1682 {
1683  int a;
1684  struct Email *e = NULL;
1685 
1686  if (!t)
1687  return 0;
1688  e = t->message;
1689  if (e)
1690  if (mutt_pattern_exec(pat, flags, m, e, NULL))
1691  return 1;
1692 
1693  if (up && (a = match_threadcomplete(pat, flags, m, t->parent, 1, 1, 1, 0)))
1694  return a;
1695  if (right && t->parent && (a = match_threadcomplete(pat, flags, m, t->next, 0, 0, 1, 1)))
1696  {
1697  return a;
1698  }
1699  if (left && t->parent && (a = match_threadcomplete(pat, flags, m, t->prev, 1, 0, 0, 1)))
1700  {
1701  return a;
1702  }
1703  if (down && (a = match_threadcomplete(pat, flags, m, t->child, 1, 0, 1, 1)))
1704  return a;
1705  return 0;
1706 }
struct MuttThread * next
Definition: thread.h:46
The envelope/body of an email.
Definition: email.h:35
struct MuttThread * parent
Definition: thread.h:44
struct MuttThread * prev
Definition: thread.h:47
struct MuttThread * child
Definition: thread.h:45
static int match_threadcomplete(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct MuttThread *t, int left, int up, int right, int down)
Match a Pattern against an email thread.
Definition: pattern.c:1679
struct Email * message
Definition: thread.h:48
int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1837

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int match_threadparent ( struct Pattern pat,
enum PatternExecFlag  flags,
struct Mailbox m,
struct MuttThread t 
)
static

Match Pattern against an email's parent.

Parameters
patPattern to match
flagsFlags, e.g. MUTT_MATCH_FULL_ADDRESS
mMailbox
tThread of email
Return values
1Success, pattern matched
0Pattern did not match
-1Error

Definition at line 1718 of file pattern.c.

1720 {
1721  if (!t || !t->parent || !t->parent->message)
1722  return 0;
1723 
1724  return mutt_pattern_exec(pat, flags, m, t->parent->message, NULL);
1725 }
struct MuttThread * parent
Definition: thread.h:44
struct Email * message
Definition: thread.h:48
int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1837

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int match_threadchildren ( struct Pattern pat,
enum PatternExecFlag  flags,
struct Mailbox m,
struct MuttThread t 
)
static

Match Pattern against an email's children.

Parameters
patPattern to match
flagsFlags, e.g. MUTT_MATCH_FULL_ADDRESS
mMailbox
tThread of email
Return values
1Success, pattern matched
0Pattern did not match
-1Error

Definition at line 1737 of file pattern.c.

1739 {
1740  if (!t || !t->child)
1741  return 0;
1742 
1743  for (t = t->child; t; t = t->next)
1744  if (t->message && mutt_pattern_exec(pat, flags, m, t->message, NULL))
1745  return 1;
1746 
1747  return 0;
1748 }
struct MuttThread * next
Definition: thread.h:46
struct MuttThread * child
Definition: thread.h:45
struct Email * message
Definition: thread.h:48
int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1837

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int match_content_type ( const struct Pattern pat,
struct Body b 
)
static

Match a Pattern against an Attachment's Content-Type.

Parameters
patPattern to match
bAttachment
Return values
1Success, pattern matched
0Pattern did not match

Definition at line 1757 of file pattern.c.

1758 {
1759  char buffer[STRING];
1760  if (!b)
1761  return 0;
1762 
1763  snprintf(buffer, sizeof(buffer), "%s/%s", TYPE(b), b->subtype);
1764 
1765  if (patmatch(pat, buffer) == 0)
1766  return 1;
1767  if (match_content_type(pat, b->parts))
1768  return 1;
1769  if (match_content_type(pat, b->next))
1770  return 1;
1771  return 0;
1772 }
static int patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:981
struct Body * next
next attachment in the list
Definition: body.h:57
char * subtype
content-type subtype
Definition: body.h:36
static int match_content_type(const struct Pattern *pat, struct Body *b)
Match a Pattern against an Attachment&#39;s Content-Type.
Definition: pattern.c:1757
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:58
#define TYPE(X)
Definition: mime.h:82
#define STRING
Definition: string2.h:35

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int match_mime_content_type ( const struct Pattern pat,
struct Mailbox m,
struct Email e 
)
static

Match a Pattern against an email's Content-Type.

Parameters
patPattern to match
mMailbox
eEmail
Return values
1Success, pattern matched
0Pattern did not match

Definition at line 1782 of file pattern.c.

1784 {
1786  return match_content_type(pat, e->content);
1787 }
struct Body * content
list of MIME parts
Definition: email.h:92
void mutt_parse_mime_message(struct Mailbox *m, struct Email *cur)
Parse a MIME email.
Definition: mutt_parse.c:50
static int match_content_type(const struct Pattern *pat, struct Body *b)
Match a Pattern against an Attachment&#39;s Content-Type.
Definition: pattern.c:1757

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void set_pattern_cache_value ( int *  cache_entry,
int  value 
)
static

Sets a value in the PatternCache cache entry.

Parameters
cache_entryCache entry to update
valueValue to set

Normalizes the "true" value to 2.

Definition at line 1796 of file pattern.c.

1797 {
1798  *cache_entry = value ? 2 : 1;
1799 }

+ Here is the caller graph for this function:

static int get_pattern_cache_value ( int  cache_entry)
static

Get pattern cache value.

Parameters
cache_entryCache entry to get
Return values
1if the cache value is set and has a true value
0otherwise (even if unset!)

Definition at line 1807 of file pattern.c.

1808 {
1809  return cache_entry == 2;
1810 }

+ Here is the caller graph for this function:

static int is_pattern_cache_set ( int  cache_entry)
static

Is a given Pattern cached?

Parameters
cache_entryCache entry to check
Return values
trueIf it is cached

Definition at line 1817 of file pattern.c.

1818 {
1819  return cache_entry != 0;
1820 }

+ Here is the caller graph for this function:

int mutt_pattern_exec ( struct Pattern pat,
enum PatternExecFlag  flags,
struct Mailbox m,
struct Email e,
struct PatternCache cache 
)

Match a pattern against an email header.

Parameters
patPattern to match
flagsFlags, e.g. MUTT_MATCH_FULL_ADDRESS
mMailbox
eEmail
cacheCache for common Patterns
Return values
1Success, pattern matched
0Pattern did not match
-1Error

flags: MUTT_MATCH_FULL_ADDRESS - match both personal and machine address cache: For repeated matches against the same Header, passing in non-NULL will store some of the cacheable pattern matches in this structure.

Definition at line 1837 of file pattern.c.

1839 {
1840  int result;
1841  int *cache_entry = NULL;
1842 
1843  switch (pat->op)
1844  {
1845  case MUTT_AND:
1846  return pat->not^(perform_and(pat->child, flags, m, e, cache) > 0);
1847  case MUTT_OR:
1848  return pat->not^(perform_or(pat->child, flags, m, e, cache) > 0);
1849  case MUTT_THREAD:
1850  return pat->not^match_threadcomplete(pat->child, flags, m, e->thread, 1, 1, 1, 1);
1851  case MUTT_PARENT:
1852  return pat->not^match_threadparent(pat->child, flags, m, e->thread);
1853  case MUTT_CHILDREN:
1854  return pat->not^match_threadchildren(pat->child, flags, m, e->thread);
1855  case MUTT_ALL:
1856  return !pat->not;
1857  case MUTT_EXPIRED:
1858  return pat->not^e->expired;
1859  case MUTT_SUPERSEDED:
1860  return pat->not^e->superseded;
1861  case MUTT_FLAG:
1862  return pat->not^e->flagged;
1863  case MUTT_TAG:
1864  return pat->not^e->tagged;
1865  case MUTT_NEW:
1866  return pat->not? e->old || e->read : !(e->old || e->read);
1867  case MUTT_UNREAD:
1868  return pat->not? e->read : !e->read;
1869  case MUTT_REPLIED:
1870  return pat->not^e->replied;
1871  case MUTT_OLD:
1872  return pat->not? (!e->old || e->read) : (e->old && !e->read);
1873  case MUTT_READ:
1874  return pat->not^e->read;
1875  case MUTT_DELETED:
1876  return pat->not^e->deleted;
1877  case MUTT_MESSAGE:
1878  return pat->not^((HMSG(e) >= pat->min) && (HMSG(e) <= pat->max));
1879  case MUTT_DATE:
1880  return pat->not^(e->date_sent >= pat->min && e->date_sent <= pat->max);
1881  case MUTT_DATE_RECEIVED:
1882  return pat->not^(e->received >= pat->min && e->received <= pat->max);
1883  case MUTT_BODY:
1884  case MUTT_HEADER:
1885  case MUTT_WHOLE_MSG:
1886  /* m can be NULL in certain cases, such as when replying to a message
1887  * from the attachment menu and the user has a reply-hook using "~e" (bug
1888  * #2190).
1889  * This is also the case when message scoring.
1890  */
1891  if (!m)
1892  return 0;
1893 #ifdef USE_IMAP
1894  /* IMAP search sets e->matched at search compile time */
1895  if (m->magic == MUTT_IMAP && pat->stringmatch)
1896  return e->matched;
1897 #endif
1898  return pat->not^msg_search(m, pat, e->msgno);
1899  case MUTT_SERVERSEARCH:
1900 #ifdef USE_IMAP
1901  if (!m)
1902  return 0;
1903  if (m->magic == MUTT_IMAP)
1904  {
1905  if (pat->stringmatch)
1906  return e->matched;
1907  return 0;
1908  }
1909  mutt_error(_("error: server custom search only supported with IMAP"));
1910  return 0;
1911 #else
1912  mutt_error(_("error: server custom search only supported with IMAP"));
1913  return -1;
1914 #endif
1915  case MUTT_SENDER:
1916  if (!e->env)
1917  return 0;
1918  return pat->not^match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1,
1919  e->env->sender);
1920  case MUTT_FROM:
1921  if (!e->env)
1922  return 0;
1923  return pat->not^match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1,
1924  e->env->from);
1925  case MUTT_TO:
1926  if (!e->env)
1927  return 0;
1928  return pat->not^match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1,
1929  e->env->to);
1930  case MUTT_CC:
1931  if (!e->env)
1932  return 0;
1933  return pat->not^match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1,
1934  e->env->cc);
1935  case MUTT_SUBJECT:
1936  if (!e->env)
1937  return 0;
1938  return pat->not^(e->env->subject &&patmatch(pat, e->env->subject) == 0);
1939  case MUTT_ID:
1940  if (!e->env)
1941  return 0;
1942  return pat->not^(e->env->message_id &&patmatch(pat, e->env->message_id) == 0);
1943  case MUTT_SCORE:
1944  return pat->not^(e->score >= pat->min &&
1945  (pat->max == MUTT_MAXRANGE || e->score <= pat->max));
1946  case MUTT_SIZE:
1947  return pat->not^(e->content->length >= pat->min &&
1948  (pat->max == MUTT_MAXRANGE || e->content->length <= pat->max));
1949  case MUTT_REFERENCE:
1950  if (!e->env)
1951  return 0;
1952  return pat->not^(match_reference(pat, &e->env->references) ||
1953  match_reference(pat, &e->env->in_reply_to));
1954  case MUTT_ADDRESS:
1955  if (!e->env)
1956  return 0;
1957  return pat->not^match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 4,
1958  e->env->from, e->env->sender, e->env->to,
1959  e->env->cc);
1960  case MUTT_RECIPIENT:
1961  if (!e->env)
1962  return 0;
1963  return pat->not^match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 2,
1964  e->env->to, e->env->cc);
1965  case MUTT_LIST: /* known list, subscribed or not */
1966  if (!e->env)
1967  return 0;
1968  if (cache)
1969  {
1970  cache_entry = pat->alladdr ? &cache->list_all : &cache->list_one;
1971  if (!is_pattern_cache_set(*cache_entry))
1972  {
1974  cache_entry, mutt_is_list_cc(pat->alladdr, e->env->to, e->env->cc));
1975  }
1976  result = get_pattern_cache_value(*cache_entry);
1977  }
1978  else
1979  result = mutt_is_list_cc(pat->alladdr, e->env->to, e->env->cc);
1980  return pat->not^result;
1981  case MUTT_SUBSCRIBED_LIST:
1982  if (!e->env)
1983  return 0;
1984  if (cache)
1985  {
1986  cache_entry = pat->alladdr ? &cache->sub_all : &cache->sub_one;
1987  if (!is_pattern_cache_set(*cache_entry))
1988  {
1990  cache_entry,
1991  mutt_is_list_recipient(pat->alladdr, e->env->to, e->env->cc));
1992  }
1993  result = get_pattern_cache_value(*cache_entry);
1994  }
1995  else
1996  result = mutt_is_list_recipient(pat->alladdr, e->env->to, e->env->cc);
1997  return pat->not^result;
1998  case MUTT_PERSONAL_RECIP:
1999  if (!e->env)
2000  return 0;
2001  if (cache)
2002  {
2003  cache_entry = pat->alladdr ? &cache->pers_recip_all : &cache->pers_recip_one;
2004  if (!is_pattern_cache_set(*cache_entry))
2005  {
2006  set_pattern_cache_value(cache_entry,
2007  match_user(pat->alladdr, e->env->to, e->env->cc));
2008  }
2009  result = get_pattern_cache_value(*cache_entry);
2010  }
2011  else
2012  result = match_user(pat->alladdr, e->env->to, e->env->cc);
2013  return pat->not^result;
2014  case MUTT_PERSONAL_FROM:
2015  if (!e->env)
2016  return 0;
2017  if (cache)
2018  {
2019  cache_entry = pat->alladdr ? &cache->pers_from_all : &cache->pers_from_one;
2020  if (!is_pattern_cache_set(*cache_entry))
2021  set_pattern_cache_value(cache_entry, match_user(pat->alladdr, e->env->from, NULL));
2022  result = get_pattern_cache_value(*cache_entry);
2023  }
2024  else
2025  result = match_user(pat->alladdr, e->env->from, NULL);
2026  return pat->not^result;
2027  case MUTT_COLLAPSED:
2028  return pat->not^(e->collapsed && e->num_hidden > 1);
2029  case MUTT_CRYPT_SIGN:
2030  if (!WithCrypto)
2031  break;
2032  return pat->not^((e->security & SIGN) ? 1 : 0);
2033  case MUTT_CRYPT_VERIFIED:
2034  if (!WithCrypto)
2035  break;
2036  return pat->not^((e->security & GOODSIGN) ? 1 : 0);
2037  case MUTT_CRYPT_ENCRYPT:
2038  if (!WithCrypto)
2039  break;
2040  return pat->not^((e->security & ENCRYPT) ? 1 : 0);
2041  case MUTT_PGP_KEY:
2042  if (!(WithCrypto & APPLICATION_PGP))
2043  break;
2044  return pat->not^((e->security & PGP_KEY) == PGP_KEY);
2045  case MUTT_XLABEL:
2046  if (!e->env)
2047  return 0;
2048  return pat->not^(e->env->x_label &&patmatch(pat, e->env->x_label) == 0);
2049  case MUTT_DRIVER_TAGS:
2050  {
2051  char *tags = driver_tags_get(&e->tags);
2052  bool ret = (pat->not^(tags &&patmatch(pat, tags) == 0));
2053  FREE(&tags);
2054  return ret;
2055  }
2056  case MUTT_HORMEL:
2057  if (!e->env)
2058  return 0;
2059  return pat->not^(e->env->spam && e->env->spam->data &&
2060  patmatch(pat, e->env->spam->data) == 0);
2061  case MUTT_DUPLICATED:
2062  return pat->not^(e->thread && e->thread->duplicate_thread);
2063  case MUTT_MIMEATTACH:
2064  if (!m)
2065  return 0;
2066  {
2067  int count = mutt_count_body_parts(m, e);
2068  return pat->not^(count >= pat->min &&
2069  (pat->max == MUTT_MAXRANGE || count <= pat->max));
2070  }
2071  case MUTT_MIMETYPE:
2072  if (!m)
2073  return 0;
2074  return pat->not^match_mime_content_type(pat, m, e);
2075  case MUTT_UNREFERENCED:
2076  return pat->not^(e->thread && !e->thread->child);
2077  case MUTT_BROKEN:
2078  return pat->not^(e->thread && e->thread->fake_thread);
2079 #ifdef USE_NNTP
2080  case MUTT_NEWSGROUPS:
2081  if (!e->env)
2082  return 0;
2083  return pat->not^(e->env->newsgroups &&patmatch(pat, e->env->newsgroups) == 0);
2084 #endif
2085  }
2086  mutt_error(_("error: unknown op %d (report this error)"), pat->op);
2087  return -1;
2088 }
Pattern matches email&#39;s size.
Definition: mutt.h:154
Pattern matches &#39;Date:&#39; field.
Definition: mutt.h:141
#define SIGN
Definition: ncrypt.h:120
static int patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:981
Email is on mailing list.
Definition: mutt.h:157
static bool match_reference(struct Pattern *pat, struct ListHead *refs)
Match references against a Pattern.
Definition: pattern.c:1595
bool not
Definition: pattern.h:47
unsigned int security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:37
int pers_recip_all
^~p
Definition: pattern.h:86
struct Address * to
Definition: envelope.h:36
Pattern matches &#39;References:&#39; or &#39;In-Reply-To:&#39; field.
Definition: mutt.h:155
Message is signed.
Definition: mutt.h:162
struct MuttThread * thread
Definition: email.h:96
static int match_addrlist(struct Pattern *pat, bool match_personal, int n,...)
Match a Pattern against and Address list.
Definition: pattern.c:1567
Unread messages.
Definition: mutt.h:117
Expired messsages.
Definition: mutt.h:126
Email is addressed to the user.
Definition: mutt.h:159
int mutt_is_list_recipient(bool alladdr, struct Address *a1, struct Address *a2)
Matches subscribed mailing lists.
Definition: pattern.c:1614
Old messages.
Definition: mutt.h:114
Message is part of a broken thread.
Definition: mutt.h:145
struct Body * content
list of MIME parts
Definition: email.h:92
Either pattern can match.
Definition: mutt.h:132
#define MUTT_MAXRANGE
Definition: pattern.c:96
Match the full address.
Definition: pattern.h:69
#define _(a)
Definition: message.h:28
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
struct TagHead tags
for drivers that support server tagging
Definition: email.h:109
Message is unreferenced in the thread.
Definition: mutt.h:144
Pattern matches date received.
Definition: mutt.h:142
Pattern matches a child email.
Definition: mutt.h:135
Pattern matches any address field.
Definition: mutt.h:161
Email is on subscribed mailing list.
Definition: mutt.h:158
Message is crypographically verified.
Definition: mutt.h:163
bool expired
already expired?
Definition: email.h:50
Message has PGP key.
Definition: mutt.h:165
Message is encrypted.
Definition: mutt.h:164
struct Address * sender
Definition: envelope.h:39
static int match_mime_content_type(const struct Pattern *pat, struct Mailbox *m, struct Email *e)
Match a Pattern against an email&#39;s Content-Type.
Definition: pattern.c:1782
Pattern matches MIME type.
Definition: mutt.h:170
int sub_all
^~u
Definition: pattern.h:84
Pattern matches keyword/label.
Definition: mutt.h:166
Both patterns must match.
Definition: mutt.h:131
static int is_pattern_cache_set(int cache_entry)
Is a given Pattern cached?
Definition: pattern.c:1817
bool tagged
Definition: email.h:42
char * driver_tags_get(struct TagHead *head)
Get tags.
Definition: tags.c:150
bool read
Definition: email.h:49
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:60
char * message_id
Definition: envelope.h:47
Email is from the user.
Definition: mutt.h:160
static int perform_or(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Perform a logical OR on a set of Patterns.
Definition: pattern.c:1549
Pattern matches raw email text.
Definition: mutt.h:150
bool old
Definition: email.h:48
enum MailboxType magic
mailbox type
Definition: mailbox.h:99
Pattern matches &#39;Subject:&#39; field.
Definition: mutt.h:139
struct Envelope * env
envelope information
Definition: email.h:91
Pattern matches email&#39;s spam score.
Definition: mutt.h:149
static int match_threadparent(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct MuttThread *t)
Match Pattern against an email&#39;s parent.
Definition: pattern.c:1718
Tagged messages.
Definition: mutt.h:123
Pattern matches number of attachments.
Definition: mutt.h:169
Deleted messages.
Definition: mutt.h:121
Thread is collapsed.
Definition: mutt.h:138
bool superseded
got superseded?
Definition: email.h:51
struct Address * from
Definition: envelope.h:35
int min
Definition: pattern.h:53
User is a recipient of the email.
Definition: mutt.h:156
int score
Definition: email.h:90
Messages that have been replied to.
Definition: mutt.h:115
time_t date_sent
time when the message was sent (UTC)
Definition: email.h:83
#define ENCRYPT
Definition: ncrypt.h:119
int pers_from_one
~P
Definition: pattern.h:89
struct MuttThread * child
Definition: thread.h:45
bool duplicate_thread
Definition: thread.h:37
Pattern matches newsgroup.
Definition: mutt.h:172
int pers_recip_one
~p
Definition: pattern.h:87
LOFF_T length
length (in bytes) of attachment
Definition: body.h:46
bool fake_thread
Definition: thread.h:36
Server-side pattern matches.
Definition: mutt.h:167
Pattern matches email&#39;s header.
Definition: mutt.h:148
New messages.
Definition: mutt.h:113
static int match_threadchildren(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct MuttThread *t)
Match Pattern against an email&#39;s children.
Definition: pattern.c:1737
size_t num_hidden
number of hidden messages in this view
Definition: email.h:77
Pattern matches sender.
Definition: mutt.h:151
#define PGP_KEY
Definition: ncrypt.h:137
Duplicate message.
Definition: mutt.h:143
char * data
pointer to data
Definition: buffer.h:35
int mutt_is_list_cc(int alladdr, struct Address *a1, struct Address *a2)
Matches known mailing lists.
Definition: pattern.c:1636
Pattern matches message number.
Definition: mutt.h:152
struct Pattern * child
arguments to logical op
Definition: pattern.h:56
int list_all
^~l
Definition: pattern.h:82
Superseded messages.
Definition: mutt.h:127
static int get_pattern_cache_value(int cache_entry)
Get pattern cache value.
Definition: pattern.c:1807
bool collapsed
is this message part of a collapsed thread?
Definition: email.h:75
static bool perform_and(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Perform a logical AND on a set of Patterns.
Definition: pattern.c:1531
short op
Definition: pattern.h:46
Pattern matches message tags.
Definition: mutt.h:168
Pattern matches &#39;Cc:&#39; field.
Definition: mutt.h:137
static int match_threadcomplete(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct MuttThread *t, int left, int up, int right, int down)
Match a Pattern against an email thread.
Definition: pattern.c:1679
#define APPLICATION_PGP
Definition: ncrypt.h:129
Pattern matches email&#39;s score.
Definition: mutt.h:153
Messages that have been read.
Definition: mutt.h:116
int pers_from_all
^~P
Definition: pattern.h:88
struct Buffer * spam
Definition: envelope.h:58
static bool msg_search(struct Mailbox *m, struct Pattern *pat, int msgno)
Search an email.
Definition: pattern.c:999
char * subject
Definition: envelope.h:44
bool flagged
marked important?
Definition: email.h:41
char * newsgroups
Definition: envelope.h:53
bool deleted
Definition: email.h:43
Pattern matches &#39;From:&#39; field.
Definition: mutt.h:140
#define mutt_error(...)
Definition: logging.h:88
bool replied
Definition: email.h:52
Pattern matches parent.
Definition: mutt.h:134
static int match_user(int alladdr, struct Address *a1, struct Address *a2)
Matches the user&#39;s email Address.
Definition: pattern.c:1655
#define FREE(x)
Definition: memory.h:46
int max
Definition: pattern.h:54
Flagged messages.
Definition: mutt.h:122
bool stringmatch
Definition: pattern.h:49
Pattern matches email&#39;s body.
Definition: mutt.h:147
bool alladdr
Definition: pattern.h:48
int mutt_count_body_parts(struct Mailbox *m, struct Email *e)
Count the MIME Body parts.
Definition: mutt_parse.c:220
static void set_pattern_cache_value(int *cache_entry, int value)
Sets a value in the PatternCache cache entry.
Definition: pattern.c:1796
All messages.
Definition: mutt.h:111
struct ListHead references
message references (in reverse order)
Definition: envelope.h:59
char * x_label
Definition: envelope.h:50
#define WithCrypto
Definition: ncrypt.h:154
int list_one
~l
Definition: pattern.h:83
time_t received
time when the message was placed in the mailbox
Definition: email.h:84
struct Address * cc
Definition: envelope.h:37
Pattern matches &#39;To:&#39; field.
Definition: mutt.h:136
bool matched
Definition: email.h:69
int msgno
number displayed to the user
Definition: email.h:88
int sub_one
~u
Definition: pattern.h:85
#define GOODSIGN
Definition: ncrypt.h:121
Pattern matches email thread.
Definition: mutt.h:133
Pattern matches email&#39;s Message-Id.
Definition: mutt.h:146
#define HMSG(h)
Definition: pattern.c:93

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void quote_simple ( const char *  str,
char *  buf,
size_t  buflen 
)
static

Apply simple quoting to a string.

Parameters
strString to quote
bufBuffer for the result
buflenLength of buffer

Definition at line 2096 of file pattern.c.

2097 {
2098  int i = 0;
2099 
2100  buf[i++] = '"';
2101  while (*str && i < buflen - 3)
2102  {
2103  if (*str == '\\' || *str == '"')
2104  buf[i++] = '\\';
2105  buf[i++] = *str++;
2106  }
2107  buf[i++] = '"';
2108  buf[i] = 0;
2109 }

+ Here is the caller graph for this function:

void mutt_check_simple ( char *  s,
size_t  len,
const char *  simple 
)

Convert a simple search into a real request.

Parameters
sBuffer for the result
lenLength of buffer
simpleSearch string to convert

Definition at line 2117 of file pattern.c.

2118 {
2119  bool do_simple = true;
2120 
2121  for (char *p = s; p && *p; p++)
2122  {
2123  if (*p == '\\' && *(p + 1))
2124  p++;
2125  else if (*p == '~' || *p == '=' || *p == '%')
2126  {
2127  do_simple = false;
2128  break;
2129  }
2130  }
2131 
2132  /* XXX - is mutt_str_strcasecmp() right here, or should we use locale's
2133  * equivalences?
2134  */
2135 
2136  if (do_simple) /* yup, so spoof a real request */
2137  {
2138  /* convert old tokens into the new format */
2139  if ((mutt_str_strcasecmp("all", s) == 0) || (mutt_str_strcmp("^", s) == 0) ||
2140  (mutt_str_strcmp(".", s) == 0)) /* ~A is more efficient */
2141  {
2142  mutt_str_strfcpy(s, "~A", len);
2143  }
2144  else if (mutt_str_strcasecmp("del", s) == 0)
2145  mutt_str_strfcpy(s, "~D", len);
2146  else if (mutt_str_strcasecmp("flag", s) == 0)
2147  mutt_str_strfcpy(s, "~F", len);
2148  else if (mutt_str_strcasecmp("new", s) == 0)
2149  mutt_str_strfcpy(s, "~N", len);
2150  else if (mutt_str_strcasecmp("old", s) == 0)
2151  mutt_str_strfcpy(s, "~O", len);
2152  else if (mutt_str_strcasecmp("repl", s) == 0)
2153  mutt_str_strfcpy(s, "~Q", len);
2154  else if (mutt_str_strcasecmp("read", s) == 0)
2155  mutt_str_strfcpy(s, "~R", len);
2156  else if (mutt_str_strcasecmp("tag", s) == 0)
2157  mutt_str_strfcpy(s, "~T", len);
2158  else if (mutt_str_strcasecmp("unread", s) == 0)
2159  mutt_str_strfcpy(s, "~U", len);
2160  else
2161  {
2162  char tmp[LONG_STRING];
2163  quote_simple(s, tmp, sizeof(tmp));
2164  mutt_file_expand_fmt(s, len, simple, tmp);
2165  }
2166  }
2167 }
static void quote_simple(const char *str, char *buf, size_t buflen)
Apply simple quoting to a string.
Definition: pattern.c:2096
void mutt_file_expand_fmt(char *dest, size_t destlen, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1338
#define LONG_STRING
Definition: string2.h:36
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:742
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:625
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:612

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static struct MuttThread* top_of_thread ( struct Email e)
static

Find the first email in the current thread.

Parameters
eCurrent Email
Return values
ptrSuccess, email found
NULLError

Definition at line 2175 of file pattern.c.

2176 {
2177  struct MuttThread *t = NULL;
2178 
2179  if (!e)
2180  return NULL;
2181 
2182  t = e->thread;
2183 
2184  while (t && t->parent)
2185  t = t->parent;
2186 
2187  return t;
2188 }
struct MuttThread * thread
Definition: email.h:96
struct MuttThread * parent
Definition: thread.h:44
An email conversation.
Definition: thread.h:34

+ Here is the caller graph for this function:

bool mutt_limit_current_thread ( struct Email e)

Limit the email view to the current thread.

Parameters
eCurrent Email
Return values
trueSuccess
falseFailure

Definition at line 2196 of file pattern.c.

2197 {
2198  struct MuttThread *me = NULL;
2199 
2200  if (!e)
2201  return false;
2202 
2203  me = top_of_thread(e);
2204  if (!me)
2205  return false;
2206 
2207  Context->mailbox->vcount = 0;
2208  Context->vsize = 0;
2209  Context->collapsed = false;
2210 
2211  for (int i = 0; i < Context->mailbox->msg_count; i++)
2212  {
2213  Context->mailbox->hdrs[i]->virtual = -1;
2214  Context->mailbox->hdrs[i]->limited = false;
2215  Context->mailbox->hdrs[i]->collapsed = false;
2216  Context->mailbox->hdrs[i]->num_hidden = 0;
2217 
2218  if (top_of_thread(Context->mailbox->hdrs[i]) == me)
2219  {
2220  struct Body *body = Context->mailbox->hdrs[i]->content;
2221 
2223  Context->mailbox->hdrs[i]->limited = true;
2225  Context->mailbox->vcount++;
2226  Context->vsize += (body->length + body->offset - body->hdr_offset);
2227  }
2228  }
2229  return true;
2230 }
The "current" mailbox.
Definition: context.h:36
int msg_count
total number of messages
Definition: mailbox.h:86
int virtual
virtual message number
Definition: email.h:89
struct Body * content
list of MIME parts
Definition: email.h:92
LOFF_T offset
offset where the actual data begins
Definition: body.h:45
struct Email ** hdrs
Definition: mailbox.h:93
int vcount
the number of virtual messages
Definition: mailbox.h:96
The body of an email.
Definition: body.h:33
struct Mailbox * mailbox
Definition: context.h:50
bool limited
is this message in a limited view?
Definition: email.h:76
off_t vsize
Definition: context.h:38
LOFF_T length
length (in bytes) of attachment
Definition: body.h:46
static struct MuttThread * top_of_thread(struct Email *e)
Find the first email in the current thread.
Definition: pattern.c:2175
size_t num_hidden
number of hidden messages in this view
Definition: email.h:77
bool collapsed
is this message part of a collapsed thread?
Definition: email.h:75
An email conversation.
Definition: thread.h:34
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:95
bool collapsed
are all threads collapsed?
Definition: context.h:48
long hdr_offset
offset in stream where the headers begin.
Definition: body.h:41

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_pattern_func ( int  op,
char *  prompt 
)

Perform some Pattern matching.

Parameters
opOperation to perform, e.g. MUTT_LIMIT
promptPrompt to show the user
Return values
0Success
-1Failure

Definition at line 2239 of file pattern.c.

2240 {
2241  struct Pattern *pat = NULL;
2242  char buf[LONG_STRING] = "", *simple = NULL;
2243  struct Buffer err;
2244  int rc = -1, padding;
2245  struct Progress progress;
2246 
2247  mutt_str_strfcpy(buf, Context->pattern, sizeof(buf));
2248  if (prompt || op != MUTT_LIMIT)
2249  if (mutt_get_field(prompt, buf, sizeof(buf), MUTT_PATTERN | MUTT_CLEAR) != 0 || !buf[0])
2250  return -1;
2251 
2252  mutt_message(_("Compiling search pattern..."));
2253 
2254  simple = mutt_str_strdup(buf);
2255  mutt_check_simple(buf, sizeof(buf), NONULL(SimpleSearch));
2256 
2257  mutt_buffer_init(&err);
2258  err.dsize = STRING;
2259  err.data = mutt_mem_malloc(err.dsize);
2260  pat = mutt_pattern_comp(buf, MUTT_FULL_MSG, &err);
2261  if (!pat)
2262  {
2263  mutt_error("%s", err.data);
2264  goto bail;
2265  }
2266 
2267 #ifdef USE_IMAP
2268  if (Context->mailbox->magic == MUTT_IMAP && imap_search(Context->mailbox, pat) < 0)
2269  goto bail;
2270 #endif
2271 
2272  mutt_progress_init(&progress, _("Executing command on matching messages..."),
2274  (op == MUTT_LIMIT) ? Context->mailbox->msg_count :
2275  Context->mailbox->vcount);
2276 
2277  if (op == MUTT_LIMIT)
2278  {
2279  Context->mailbox->vcount = 0;
2280  Context->vsize = 0;
2281  Context->collapsed = false;
2282  padding = mx_msg_padding_size(Context->mailbox);
2283 
2284  for (int i = 0; i < Context->mailbox->msg_count; i++)
2285  {
2286  mutt_progress_update(&progress, i, -1);
2287  /* new limit pattern implicitly uncollapses all threads */
2288  Context->mailbox->hdrs[i]->virtual = -1;
2289  Context->mailbox->hdrs[i]->limited = false;
2290  Context->mailbox->hdrs[i]->collapsed = false;
2291  Context->mailbox->hdrs[i]->num_hidden = 0;
2293  Context->mailbox->hdrs[i], NULL))
2294  {
2296  Context->mailbox->hdrs[i]->limited = true;
2298  Context->mailbox->vcount++;
2299  struct Body *b = Context->mailbox->hdrs[i]->content;
2300  Context->vsize += b->length + b->offset - b->hdr_offset + padding;
2301  }
2302  }
2303  }
2304  else
2305  {
2306  for (int i = 0; i < Context->mailbox->vcount; i++)
2307  {
2308  mutt_progress_update(&progress, i, -1);
2310  Context->mailbox->hdrs[Context->mailbox->v2r[i]], NULL))
2311  {
2312  switch (op)
2313  {
2314  case MUTT_UNDELETE:
2317  MUTT_PURGE, 0);
2318  /* fallthrough */
2319  case MUTT_DELETE:
2322  MUTT_DELETE, (op == MUTT_DELETE));
2323  break;
2324  case MUTT_TAG:
2325  case MUTT_UNTAG:
2328  MUTT_TAG, (op == MUTT_TAG));
2329  break;
2330  }
2331  }
2332  }
2333  }
2334 
2335  mutt_clear_error();
2336 
2337  if (op == MUTT_LIMIT)
2338  {
2339  /* drop previous limit pattern */
2340  FREE(&Context->pattern);
2341  if (Context->limit_pattern)
2343 
2345  mutt_error(_("No messages matched criteria"));
2346 
2347  /* record new limit pattern, unless match all */
2348  char *pbuf = buf;
2349  while (*pbuf == ' ')
2350  pbuf++;
2351  if (mutt_str_strcmp(pbuf, "~A") != 0)
2352  {
2353  Context->pattern = simple;
2354  simple = NULL; /* don't clobber it */
2356  }
2357  }
2358 
2359  rc = 0;
2360 
2361 bail:
2362  FREE(&simple);
2363  mutt_pattern_free(&pat);
2364  FREE(&err.data);
2365 
2366  return rc;
2367 }
The "current" mailbox.
Definition: context.h:36
#define MUTT_PROGRESS_MSG
message-based progress
Definition: progress.h:33
#define NONULL(x)
Definition: string2.h:39
int msg_count
total number of messages
Definition: mailbox.h:86
#define MUTT_CLEAR
clear input if printable character is pressed
Definition: mutt.h:63
int imap_search(struct Mailbox *m, const struct Pattern *pat)
Find a matching mailbox.
Definition: imap.c:1357
#define mutt_message(...)
Definition: logging.h:87
Messages to be deleted.
Definition: mutt.h:118
int virtual
virtual message number
Definition: email.h:89
WHERE char * SimpleSearch
Config: Pattern to search for when search doesn&#39;t contain ~&#39;s.
Definition: globals.h:143
struct Body * content
list of MIME parts
Definition: email.h:92
#define MUTT_FULL_MSG
Definition: pattern.h:39
void mutt_progress_update(struct Progress *progress, long pos, int percent)
Update the state of the progress bar.
Definition: progress.c:170
void mutt_progress_init(struct Progress *progress, const char *msg, unsigned short flags, unsigned short inc, size_t size)
Set up a progress bar.
Definition: progress.c:113
String manipulation buffer.
Definition: buffer.h:33
LOFF_T offset
offset where the actual data begins
Definition: body.h:45
Match the full address.
Definition: pattern.h:69
#define _(a)
Definition: message.h:28
void mutt_pattern_free(struct Pattern **pat)
Free a Pattern.
Definition: pattern.c:1248
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
#define LONG_STRING
Definition: string2.h:36
A progress bar.
Definition: progress.h:38
#define MUTT_PATTERN
pattern mode - only used for history classes
Definition: mutt.h:65
struct Email ** hdrs
Definition: mailbox.h:93
int vcount
the number of virtual messages
Definition: mailbox.h:96
The body of an email.
Definition: body.h:33
A simple (non-regex) pattern.
Definition: pattern.h:44
struct Mailbox * mailbox
Definition: context.h:50
enum MailboxType magic
mailbox type
Definition: mailbox.h:99
Tagged messages.
Definition: mutt.h:123
bool limited
is this message in a limited view?
Definition: email.h:76
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
off_t vsize
Definition: context.h:38
Messages to be un-tagged.
Definition: mutt.h:124
LOFF_T length
length (in bytes) of attachment
Definition: body.h:46
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
size_t num_hidden
number of hidden messages in this view
Definition: email.h:77
Messages to be purged (bypass trash)
Definition: mutt.h:120
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:742
#define mutt_set_flag(a, b, c, d)
Definition: protos.h:54
bool collapsed
is this message part of a collapsed thread?
Definition: email.h:75
WHERE short ReadInc
Config: Update the progress bar after this many records read (0 to disable)
Definition: globals.h:153
#define mutt_get_field(A, B, C, D)
Definition: curs_lib.h:78
struct Pattern * limit_pattern
compiled limit pattern
Definition: context.h:40
struct Pattern * mutt_pattern_comp(char *s, int flags, struct Buffer *err)
Create a Pattern.
Definition: pattern.c:1289
Messages in limited view.
Definition: mutt.h:125
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:95
#define STRING
Definition: string2.h:35
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:384
bool collapsed
are all threads collapsed?
Definition: context.h:48
#define mutt_error(...)
Definition: logging.h:88
void mutt_check_simple(char *s, size_t len, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:2117
#define FREE(x)
Definition: memory.h:46
Messages to be un-deleted.
Definition: mutt.h:119
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size.
Definition: mx.c:1660
long hdr_offset
offset in stream where the headers begin.
Definition: body.h:41
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:66
int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1837
char * pattern
limit pattern string
Definition: context.h:39
static unsigned char * pbuf
Cache PGP data packet.
Definition: pgppacket.c:37
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:612

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_search_command ( int  cur,
int  op 
)

Perform a search.

Parameters
curIndex number of current email
opOperation to perform, e.g. OP_SEARCH_NEXT
Return values
>=0 Index of matching email
-1No match, or error

Definition at line 2376 of file pattern.c.

2377 {
2378  struct Progress progress;
2379 
2380  if (!*LastSearch || (op != OP_SEARCH_NEXT && op != OP_SEARCH_OPPOSITE))
2381  {
2382  char buf[STRING];
2383  mutt_str_strfcpy(buf, *LastSearch ? LastSearch : "", sizeof(buf));
2384  if (mutt_get_field((op == OP_SEARCH || op == OP_SEARCH_NEXT) ?
2385  _("Search for: ") :
2386  _("Reverse search for: "),
2387  buf, sizeof(buf), MUTT_CLEAR | MUTT_PATTERN) != 0 ||
2388  !buf[0])
2389  {
2390  return -1;
2391  }
2392 
2393  if (op == OP_SEARCH || op == OP_SEARCH_NEXT)
2394  OptSearchReverse = false;
2395  else
2396  OptSearchReverse = true;
2397 
2398  /* compare the *expanded* version of the search pattern in case
2399  $simple_search has changed while we were searching */
2400  char temp[LONG_STRING];
2401  mutt_str_strfcpy(temp, buf, sizeof(temp));
2402  mutt_check_simple(temp, sizeof(temp), NONULL(SimpleSearch));
2403 
2404  if (!SearchPattern || (mutt_str_strcmp(temp, LastSearchExpn) != 0))
2405  {
2406  struct Buffer err;
2407  mutt_buffer_init(&err);
2408  OptSearchInvalid = true;
2409  mutt_str_strfcpy(LastSearch, buf, sizeof(LastSearch));
2410  mutt_message(_("Compiling search pattern..."));
2412  err.dsize = STRING;
2413  err.data = mutt_mem_malloc(err.dsize);
2415  if (!SearchPattern)
2416  {
2417  mutt_error("%s", err.data);
2418  FREE(&err.data);
2419  LastSearch[0] = '\0';
2420  return -1;
2421  }
2422  FREE(&err.data);
2423  mutt_clear_error();
2424  }
2425  }
2426 
2427  if (OptSearchInvalid)
2428  {
2429  for (int i = 0; i < Context->mailbox->msg_count; i++)
2430  Context->mailbox->hdrs[i]->searched = false;
2431 #ifdef USE_IMAP
2432  if (Context->mailbox->magic == MUTT_IMAP &&
2434  return -1;
2435 #endif
2436  OptSearchInvalid = false;
2437  }
2438 
2439  int incr = (OptSearchReverse) ? -1 : 1;
2440  if (op == OP_SEARCH_OPPOSITE)
2441  incr = -incr;
2442 
2443  mutt_progress_init(&progress, _("Searching..."), MUTT_PROGRESS_MSG, ReadInc,
2444  Context->mailbox->vcount);
2445 
2446  for (int i = cur + incr, j = 0; j != Context->mailbox->vcount; j++)
2447  {
2448  const char *msg = NULL;
2449  mutt_progress_update(&progress, j, -1);
2450  if (i > Context->mailbox->vcount - 1)
2451  {
2452  i = 0;
2453  if (WrapSearch)
2454  msg = _("Search wrapped to top");
2455  else
2456  {
2457  mutt_message(_("Search hit bottom without finding match"));
2458  return -1;
2459  }
2460  }
2461  else if (i < 0)
2462  {
2463  i = Context->mailbox->vcount - 1;
2464  if (WrapSearch)
2465  msg = _("Search wrapped to bottom");
2466  else
2467  {
2468  mutt_message(_("Search hit top without finding match"));
2469  return -1;
2470  }
2471  }
2472 
2473  struct Email *e = Context->mailbox->hdrs[Context->mailbox->v2r[i]];
2474  if (e->searched)
2475  {
2476  /* if we've already evaluated this message, use the cached value */
2477  if (e->matched)
2478  {
2479  mutt_clear_error();
2480  if (msg && *msg)
2481  mutt_message(msg);
2482  return i;
2483  }
2484  }
2485  else
2486  {
2487  /* remember that we've already searched this message */
2488  e->searched = true;
2490  Context->mailbox, e, NULL);
2491  if (e->matched > 0)
2492  {
2493  mutt_clear_error();
2494  if (msg && *msg)
2495  mutt_message(msg);
2496  return i;
2497  }
2498  }
2499 
2500  if (SigInt)
2501  {
2502  mutt_error(_("Search interrupted"));
2503  SigInt = 0;
2504  return -1;
2505  }
2506 
2507  i += incr;
2508  }
2509 
2510  mutt_error(_("Not found"));
2511  return -1;
2512 }
The "current" mailbox.
Definition: context.h:36
#define MUTT_PROGRESS_MSG
message-based progress
Definition: progress.h:33
#define NONULL(x)
Definition: string2.h:39
int msg_count
total number of messages
Definition: mailbox.h:86
The envelope/body of an email.
Definition: email.h:35
#define MUTT_CLEAR
clear input if printable character is pressed
Definition: mutt.h:63
int imap_search(struct Mailbox *m, const struct Pattern *pat)
Find a matching mailbox.
Definition: imap.c:1357
#define mutt_message(...)
Definition: logging.h:87
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:90
WHERE char * SimpleSearch
Config: Pattern to search for when search doesn&#39;t contain ~&#39;s.
Definition: globals.h:143
#define MUTT_FULL_MSG
Definition: pattern.h:39
void mutt_progress_update(struct Progress *progress, long pos, int percent)
Update the state of the progress bar.
Definition: progress.c:170
void mutt_progress_init(struct Progress *progress, const char *msg, unsigned short flags, unsigned short inc, size_t size)
Set up a progress bar.
Definition: progress.c:113
String manipulation buffer.
Definition: buffer.h:33
Match the full address.
Definition: pattern.h:69
#define _(a)
Definition: message.h:28
void mutt_pattern_free(struct Pattern **pat)
Free a Pattern.
Definition: pattern.c:1248
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
static char LastSearch[STRING]
last pattern searched for
Definition: pattern.c:187
bool searched
Definition: email.h:68
#define LONG_STRING
Definition: string2.h:36
A progress bar.
Definition: progress.h:38
#define MUTT_PATTERN
pattern mode - only used for history classes
Definition: mutt.h:65
struct Email ** hdrs
Definition: mailbox.h:93
int vcount
the number of virtual messages
Definition: mailbox.h:96
static char LastSearchExpn[LONG_STRING]
expanded version of LastSearch
Definition: pattern.c:188
struct Mailbox * mailbox
Definition: context.h:50
enum MailboxType magic
mailbox type
Definition: mailbox.h:99
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
static struct Pattern * SearchPattern
current search pattern
Definition: pattern.c:186
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:99
WHERE bool WrapSearch
Config: Wrap around when the search hits the end.
Definition: globals.h:263
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:742
WHERE bool OptSearchInvalid
(pseudo) used to invalidate the search pat
Definition: options.h:49
WHERE short ReadInc
Config: Update the progress bar after this many records read (0 to disable)
Definition: globals.h:153
#define mutt_get_field(A, B, C, D)
Definition: curs_lib.h:78
struct Pattern * mutt_pattern_comp(char *s, int flags, struct Buffer *err)
Create a Pattern.
Definition: pattern.c:1289
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:95
#define STRING
Definition: string2.h:35
#define mutt_error(...)
Definition: logging.h:88
void mutt_check_simple(char *s, size_t len, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:2117
#define FREE(x)
Definition: memory.h:46
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:66
int mutt_pattern_exec(struct Pattern *pat, enum PatternExecFlag flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1837
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:612
WHERE bool OptSearchReverse
(pseudo) used by ci_search_command
Definition: options.h:50
bool matched
Definition: email.h:69

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

bool ThoroughSearch

Config: Decode headers and messages before searching them.

Definition at line 71 of file pattern.c.

struct RangeRegex range_regexes[]
static
Initial value:
= {
[RANGE_K_REL] = { RANGE_REL_RX, 1, 3, 0 },
[RANGE_K_ABS] = { RANGE_ABS_RX, 1, 3, 0 },
[RANGE_K_LT] = { RANGE_LT_RX, 1, 2, 0 },
[RANGE_K_GT] = { RANGE_GT_RX, 2, 1, 0 },
[RANGE_K_BARE] = { RANGE_BARE_RX, 1, 1, 0 },
}
Single symbol.
Definition: pattern.c:146
#define RANGE_REL_RX
Definition: pattern.c:77
#define RANGE_ABS_RX
Definition: pattern.c:81
Greater-than range.
Definition: pattern.c:145
#define RANGE_LT_RX
Definition: pattern.c:84
#define RANGE_BARE_RX
Definition: pattern.c:88
Absolute range.
Definition: pattern.c:143
#define RANGE_GT_RX
Definition: pattern.c:85
Less-than range.
Definition: pattern.c:144
Relative range.
Definition: pattern.c:142

Set of Regexes for various range types.

This array, will also contain the compiled regexes.

Definition at line 177 of file pattern.c.

struct Pattern* SearchPattern = NULL
static

current search pattern

Definition at line 186 of file pattern.c.

char LastSearch[STRING] = { 0 }
static

last pattern searched for

Definition at line 187 of file pattern.c.

char LastSearchExpn[LONG_STRING] = { 0 }
static

expanded version of LastSearch

Definition at line 188 of file pattern.c.

const struct PatternFlags Flags[]
static

Lookup table for all patterns.

Definition at line 1153 of file pattern.c.