NeoMutt  2018-07-16 +2225-8687db
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 "address/lib.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 "core/lib.h"
#include "curs_lib.h"
#include "filter.h"
#include "globals.h"
#include "handler.h"
#include "hdrline.h"
#include "mutt_logging.h"
#include "mutt_menu.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"

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 EMSG(e)   (((e)->msgno) + 1)
 
#define CTX_MSGNO(ctx)   (EMSG((ctx)->mailbox->emails[(ctx)->mailbox->v2r[(ctx)->menu->current]]))
 
#define MUTT_MAXRANGE   -1
 
#define MUTT_PDR_NO_FLAGS   0
 No flags are set. More...
 
#define MUTT_PDR_MINUS   (1 << 0)
 Pattern contains a range. More...
 
#define MUTT_PDR_PLUS   (1 << 1)
 Extend the range using '+'. More...
 
#define MUTT_PDR_WINDOW   (1 << 2)
 Extend the range in both directions using '*'. More...
 
#define MUTT_PDR_ABSOLUTE   (1 << 3)
 Absolute pattern range. More...
 
#define MUTT_PDR_DONE   (1 << 4)
 Pattern parse successfully. More...
 
#define MUTT_PDR_ERROR   (1 << 8)
 Invalid pattern. More...
 
#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   '>'
 

Typedefs

typedef uint16_t ParseDateRangeFlags
 Flags for parse_date_range(), e.g. MUTT_PDR_MINUS. More...
 
typedef bool pattern_eat_t(struct Pattern *pat, int flags, struct Buffer *s, struct Buffer *err)
 typedef pattern_eat_t - Parse a pattern More...
 
typedef bool(* addr_predicate_t) (const struct Address *a)
 typedef addr_predicate_t - Test an Address for some condition More...
 

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, int flags, struct Buffer *s, struct Buffer *err)
 Parse a regex - Implements pattern_eat_t. More...
 
static bool add_query_msgid (char *line, int line_num, void *user_data)
 Parse a Message-Id and add it to a list - Implements mutt_file_map_t. More...
 
static bool eat_query (struct Pattern *pat, int flags, struct Buffer *s, struct Buffer *err)
 Parse a query for an external search program - Implements pattern_eat_t. 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 eval_date_minmax (struct Pattern *pat, const char *s, struct Buffer *err)
 Evaluate a date-range pattern against 'now'. More...
 
static bool eat_range (struct Pattern *pat, int flags, struct Buffer *s, struct Buffer *err)
 Parse a number range - Implements pattern_eat_t. 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, int flags, struct Buffer *s, struct Buffer *err)
 Parse a range of message numbers - Implements pattern_eat_t. More...
 
static bool eat_date (struct Pattern *pat, int flags, struct Buffer *s, struct Buffer *err)
 Parse a date pattern - Implements pattern_eat_t. More...
 
static bool 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 PatternHead **pat)
 Free a Pattern. More...
 
static struct PatternHead * mutt_pattern_node_new (void)
 Create a new list containing a Pattern. More...
 
struct PatternHead * mutt_pattern_comp (const char *s, int flags, struct Buffer *err)
 Create a Pattern. More...
 
static bool perform_and (struct PatternHead *pat, PatternExecFlags 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 PatternHead *pat, PatternExecFlags 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...
 
static int mutt_is_predicate_recipient (bool alladdr, struct Envelope *e, addr_predicate_t p)
 Test an Envelopes Addresses using a predicate function. More...
 
int mutt_is_subscribed_list_recipient (bool alladdr, struct Envelope *e)
 Matches subscribed mailing lists. More...
 
int mutt_is_list_recipient (bool alladdr, struct Envelope *e)
 Matches known mailing lists. More...
 
static int match_user (int alladdr, struct AddressList *al1, struct AddressList *al2)
 Matches the user's email Address. More...
 
static int match_threadcomplete (struct PatternHead *pat, PatternExecFlags 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 PatternHead *pat, PatternExecFlags flags, struct Mailbox *m, struct MuttThread *t)
 Match Pattern against an email's parent. More...
 
static int match_threadchildren (struct PatternHead *pat, PatternExecFlags flags, struct Mailbox *m, struct MuttThread *t)
 Match Pattern against an email's children. More...
 
static bool match_content_type (const struct Pattern *pat, struct Body *b)
 Match a Pattern against an Attachment's Content-Type. More...
 
static bool match_update_dynamic_date (struct Pattern *pat)
 Update a dynamic date pattern. More...
 
static bool 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, PatternExecFlags 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, struct Buffer *buf)
 Apply simple quoting to a string. More...
 
void mutt_check_simple (struct Buffer *buf, 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 C_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 PatternHead * SearchPattern = NULL
 current search pattern More...
 
static char LastSearch [256] = { 0 }
 last pattern searched for More...
 
static char LastSearchExpn [1024] = { 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
  • Pietro Cerutti

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 77 of file pattern.c.

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

Definition at line 78 of file pattern.c.

#define RANGE_REL_RX   "^" RANGE_REL_SLOT_RX "," RANGE_REL_SLOT_RX

Definition at line 79 of file pattern.c.

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

Definition at line 82 of file pattern.c.

#define RANGE_ABS_RX   "^" RANGE_ABS_SLOT_RX "-" RANGE_ABS_SLOT_RX

Definition at line 83 of file pattern.c.

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

Definition at line 86 of file pattern.c.

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

Definition at line 87 of file pattern.c.

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

Definition at line 90 of file pattern.c.

#define RANGE_RX_GROUPS   5

Definition at line 91 of file pattern.c.

#define KILO   1024

Definition at line 93 of file pattern.c.

#define MEGA   1048576

Definition at line 94 of file pattern.c.

#define EMSG (   e)    (((e)->msgno) + 1)

Definition at line 95 of file pattern.c.

#define CTX_MSGNO (   ctx)    (EMSG((ctx)->mailbox->emails[(ctx)->mailbox->v2r[(ctx)->menu->current]]))

Definition at line 96 of file pattern.c.

#define MUTT_MAXRANGE   -1

Definition at line 99 of file pattern.c.

#define MUTT_PDR_NO_FLAGS   0

No flags are set.

Definition at line 102 of file pattern.c.

#define MUTT_PDR_MINUS   (1 << 0)

Pattern contains a range.

Definition at line 103 of file pattern.c.

#define MUTT_PDR_PLUS   (1 << 1)

Extend the range using '+'.

Definition at line 104 of file pattern.c.

#define MUTT_PDR_WINDOW   (1 << 2)

Extend the range in both directions using '*'.

Definition at line 105 of file pattern.c.

#define MUTT_PDR_ABSOLUTE   (1 << 3)

Absolute pattern range.

Definition at line 106 of file pattern.c.

#define MUTT_PDR_DONE   (1 << 4)

Pattern parse successfully.

Definition at line 107 of file pattern.c.

#define MUTT_PDR_ERROR   (1 << 8)

Invalid pattern.

Definition at line 108 of file pattern.c.

#define MUTT_PDR_ERRORDONE   (MUTT_PDR_ERROR | MUTT_PDR_DONE)

Definition at line 110 of file pattern.c.

#define RANGE_DOT   '.'

Definition at line 112 of file pattern.c.

#define RANGE_CIRCUM   '^'

Definition at line 113 of file pattern.c.

#define RANGE_DOLLAR   '$'

Definition at line 114 of file pattern.c.

#define RANGE_LT   '<'

Definition at line 115 of file pattern.c.

#define RANGE_GT   '>'

Definition at line 116 of file pattern.c.

Typedef Documentation

typedef uint16_t ParseDateRangeFlags

Flags for parse_date_range(), e.g. MUTT_PDR_MINUS.

Definition at line 101 of file pattern.c.

typedef bool pattern_eat_t(struct Pattern *pat, int flags, struct Buffer *s, struct Buffer *err)

typedef pattern_eat_t - Parse a pattern

Parameters
patPattern to store the results in
flagsFlags, e.g. MUTT_PATTERN_DYNAMIC
sString to parse
errBuffer for error messages
Return values
trueIf the pattern was read successfully

Definition at line 172 of file pattern.c.

typedef bool(* addr_predicate_t) (const struct Address *a)

typedef addr_predicate_t - Test an Address for some condition

Parameters
aAddress to test
Return values
boolTrue if Address matches the test

Definition at line 1736 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 122 of file pattern.c.

123 {
124  RANGE_E_OK,
126  RANGE_E_CTX,
127 };
Range is valid.
Definition: pattern.c:124
Range contains syntax error.
Definition: pattern.c:125
Range requires Context, but none available.
Definition: pattern.c:126
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 144 of file pattern.c.

145 {
146  RANGE_K_REL,
147  RANGE_K_ABS,
148  RANGE_K_LT,
149  RANGE_K_GT,
150  RANGE_K_BARE,
151  /* add new ones HERE */
153 };
Single symbol.
Definition: pattern.c:150
Greater-than range.
Definition: pattern.c:149
Range is invalid.
Definition: pattern.c:152
Absolute range.
Definition: pattern.c:147
Less-than range.
Definition: pattern.c:148
Relative range.
Definition: pattern.c:146
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 158 of file pattern.c.

159 {
160  RANGE_S_LEFT,
161  RANGE_S_RIGHT,
162 };
Left side of range.
Definition: pattern.c:160
Right side of range.
Definition: pattern.c:161

Function Documentation

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

Parse a regex - Implements pattern_eat_t.

Definition at line 208 of file pattern.c.

209 {
210  struct Buffer buf;
211 
212  mutt_buffer_init(&buf);
213  char *pexpr = s->dptr;
214  if ((mutt_extract_token(&buf, s, MUTT_TOKEN_PATTERN | MUTT_TOKEN_COMMENT) != 0) || !buf.data)
215  {
216  mutt_buffer_printf(err, _("Error in expression: %s"), pexpr);
217  FREE(&buf.data);
218  return false;
219  }
220  if (buf.data[0] == '\0')
221  {
222  mutt_buffer_printf(err, "%s", _("Empty expression"));
223  FREE(&buf.data);
224  return false;
225  }
226 
227  if (pat->stringmatch)
228  {
229  pat->p.str = mutt_str_strdup(buf.data);
230  pat->ign_case = mutt_mb_is_lower(buf.data);
231  FREE(&buf.data);
232  }
233  else if (pat->groupmatch)
234  {
235  pat->p.group = mutt_pattern_group(buf.data);
236  FREE(&buf.data);
237  }
238  else
239  {
240  pat->p.regex = mutt_mem_malloc(sizeof(regex_t));
241  int case_flags = mutt_mb_is_lower(buf.data) ? REG_ICASE : 0;
242  int rc = REG_COMP(pat->p.regex, buf.data, REG_NEWLINE | REG_NOSUB | case_flags);
243  if (rc != 0)
244  {
245  char errmsg[256];
246  regerror(rc, pat->p.regex, errmsg, sizeof(errmsg));
247  mutt_buffer_add_printf(err, "'%s': %s", buf.data, errmsg);
248  FREE(&buf.data);
249  FREE(&pat->p.regex);
250  return false;
251  }
252  FREE(&buf.data);
253  }
254 
255  return true;
256 }
regex_t * regex
Definition: pattern.h:63
#define MUTT_TOKEN_COMMENT
Don&#39;t reap comments.
Definition: mutt.h:82
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:191
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:52
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:234
bool ign_case
ignore case for local stringmatch searches
Definition: pattern.h:54
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:2614
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
char * dptr
Current read/write position.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:35
union Pattern::@2 p
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
char * str
Definition: pattern.h:65
struct Group * group
Definition: pattern.h:64
#define FREE(x)
Definition: memory.h:40
bool groupmatch
Definition: pattern.h:53
bool stringmatch
Definition: pattern.h:52
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:61
bool mutt_mb_is_lower(const char *s)
Does a multi-byte string contain only lowercase characters?
Definition: mbyte.c:358
#define MUTT_TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition: mutt.h:81
struct Group * mutt_pattern_group(const char *pat)
Match a pattern to a Group.
Definition: group.c:66
static bool add_query_msgid ( char *  line,
int  line_num,
void *  user_data 
)
static

Parse a Message-Id and add it to a list - Implements mutt_file_map_t.

Return values
trueAlways

Definition at line 262 of file pattern.c.

263 {
264  struct ListHead *msgid_list = (struct ListHead *) (user_data);
265  char *nows = mutt_str_skip_whitespace(line);
266  if (!*nows)
267  return true;
269  mutt_list_insert_tail(msgid_list, mutt_str_strdup(nows));
270  return true;
271 }
char * mutt_str_skip_whitespace(const char *p)
Find the first non-whitespace character in a string.
Definition: string.c:720
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:65
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:734
const char * line
Definition: common.c:36
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
static bool eat_query ( struct Pattern pat,
int  flags,
struct Buffer s,
struct Buffer err 
)
static

Parse a query for an external search program - Implements pattern_eat_t.

Definition at line 276 of file pattern.c.

277 {
278  struct Buffer cmd_buf;
279  struct Buffer tok_buf;
280  FILE *fp = NULL;
281 
283  {
284  mutt_buffer_printf(err, "%s", _("No search command defined"));
285  return false;
286  }
287 
288  mutt_buffer_init(&tok_buf);
289  char *pexpr = s->dptr;
290  if ((mutt_extract_token(&tok_buf, s, MUTT_TOKEN_PATTERN | MUTT_TOKEN_COMMENT) != 0) ||
291  !tok_buf.data)
292  {
293  mutt_buffer_printf(err, _("Error in expression: %s"), pexpr);
294  return false;
295  }
296  if (*tok_buf.data == '\0')
297  {
298  mutt_buffer_printf(err, "%s", _("Empty expression"));
299  FREE(&tok_buf.data);
300  return false;
301  }
302 
303  mutt_buffer_init(&cmd_buf);
305  mutt_buffer_addch(&cmd_buf, ' ');
306  if (!Context || !Context->mailbox)
307  {
308  mutt_buffer_addch(&cmd_buf, '/');
309  }
310  else
311  {
312  char *escaped_folder = mutt_path_escape(mutt_b2s(Context->mailbox->pathbuf));
313  mutt_debug(LL_DEBUG2, "escaped folder path: %s\n", escaped_folder);
314  mutt_buffer_addch(&cmd_buf, '\'');
315  mutt_buffer_addstr(&cmd_buf, escaped_folder);
316  mutt_buffer_addch(&cmd_buf, '\'');
317  }
318  mutt_buffer_addch(&cmd_buf, ' ');
319  mutt_buffer_addstr(&cmd_buf, tok_buf.data);
320  FREE(&tok_buf.data);
321 
322  mutt_message(_("Running search command: %s ..."), cmd_buf.data);
323  pat->ismulti = true;
325  pid_t pid = mutt_create_filter(cmd_buf.data, NULL, &fp, NULL);
326  if (pid < 0)
327  {
328  mutt_buffer_printf(err, "unable to fork command: %s\n", cmd_buf.data);
329  FREE(&cmd_buf.data);
330  return false;
331  }
332 
334  mutt_file_fclose(&fp);
335  mutt_wait_filter(pid);
336  FREE(&cmd_buf.data);
337  return true;
338 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:216
The "current" mailbox.
Definition: context.h:39
#define mutt_message(...)
Definition: logging.h:83
#define MUTT_TOKEN_COMMENT
Don&#39;t reap comments.
Definition: mutt.h:82
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:191
struct Mailbox * mailbox
Definition: context.h:53
Log at debug level 2.
Definition: logging.h:57
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
bool mutt_file_map_lines(mutt_file_map_t func, void *user_data, FILE *fp, int flags)
Process lines of text read from a file pointer.
Definition: file.c:763
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:256
#define mutt_b2s(buf)
Definition: buffer.h:42
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:2614
char * dptr
Current read/write position.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:35
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:271
static bool add_query_msgid(char *line, int line_num, void *user_data)
Parse a Message-Id and add it to a list - Implements mutt_file_map_t.
Definition: pattern.c:262
struct Buffer * pathbuf
Definition: mailbox.h:95
union Pattern::@2 p
#define FREE(x)
Definition: memory.h:40
struct ListHead multi_cases
Definition: pattern.h:66
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:61
WHERE char * C_ExternalSearchCommand
Config: External search command.
Definition: globals.h:105
void mutt_list_clear(struct ListHead *h)
Free a list, but NOT its strings.
Definition: list.c:168
int mutt_wait_filter(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:227
#define MUTT_TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition: mutt.h:81
bool ismulti
multiple case (only for I pattern now)
Definition: pattern.h:57
char * mutt_path_escape(const char *src)
Escapes single quotes in a path for a command string.
Definition: path.c:555
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 352 of file pattern.c.

353 {
354  char *ps = NULL;
355  int offset = strtol(s, &ps, 0);
356  if (((sign < 0) && (offset > 0)) || ((sign > 0) && (offset < 0)))
357  offset = -offset;
358 
359  switch (*ps)
360  {
361  case 'y':
362  tm->tm_year += offset;
363  break;
364  case 'm':
365  tm->tm_mon += offset;
366  break;
367  case 'w':
368  tm->tm_mday += 7 * offset;
369  break;
370  case 'd':
371  tm->tm_mday += offset;
372  break;
373  case 'H':
374  tm->tm_hour += offset;
375  break;
376  case 'M':
377  tm->tm_min += offset;
378  break;
379  case 'S':
380  tm->tm_sec += offset;
381  break;
382  default:
383  return s;
384  }
386  return ps + 1;
387 }
void mutt_date_normalize_time(struct tm *tm)
Fix the contents of a struct tm.
Definition: date.c:289
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 405 of file pattern.c.

406 {
407  char *p = NULL;
408  struct tm tm = mutt_date_localtime(MUTT_DATE_NOW);
409 
410  t->tm_mday = strtol(s, &p, 10);
411  if ((t->tm_mday < 1) || (t->tm_mday > 31))
412  {
413  mutt_buffer_printf(err, _("Invalid day of month: %s"), s);
414  return NULL;
415  }
416  if (*p != '/')
417  {
418  /* fill in today's month and year */
419  t->tm_mon = tm.tm_mon;
420  t->tm_year = tm.tm_year;
421  return p;
422  }
423  p++;
424  t->tm_mon = strtol(p, &p, 10) - 1;
425  if ((t->tm_mon < 0) || (t->tm_mon > 11))
426  {
427  mutt_buffer_printf(err, _("Invalid month: %s"), p);
428  return NULL;
429  }
430  if (*p != '/')
431  {
432  t->tm_year = tm.tm_year;
433  return p;
434  }
435  p++;
436  t->tm_year = strtol(p, &p, 10);
437  if (t->tm_year < 70) /* year 2000+ */
438  t->tm_year += 100;
439  else if (t->tm_year > 1900)
440  t->tm_year -= 1900;
441  return p;
442 }
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:713
#define _(a)
Definition: message.h:28
#define MUTT_DATE_NOW
Constant representing the &#39;current time&#39;, see: mutt_date_gmtime(), mutt_date_localtime() ...
Definition: date.h:36
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:191
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 454 of file pattern.c.

456 {
458  while (*pc && ((flags & MUTT_PDR_DONE) == 0))
459  {
460  const char *pt = NULL;
461  char ch = *pc++;
462  SKIPWS(pc);
463  switch (ch)
464  {
465  case '-':
466  {
467  /* try a range of absolute date minus offset of Ndwmy */
468  pt = get_offset(min, pc, -1);
469  if (pc == pt)
470  {
471  if (flags == MUTT_PDR_NO_FLAGS)
472  { /* nothing yet and no offset parsed => absolute date? */
473  if (!get_date(pc, max, err))
474  flags |= (MUTT_PDR_ABSOLUTE | MUTT_PDR_ERRORDONE); /* done bad */
475  else
476  {
477  /* reestablish initial base minimum if not specified */
478  if (!have_min)
479  memcpy(min, base_min, sizeof(struct tm));
480  flags |= (MUTT_PDR_ABSOLUTE | MUTT_PDR_DONE); /* done good */
481  }
482  }
483  else
484  flags |= MUTT_PDR_ERRORDONE;
485  }
486  else
487  {
488  pc = pt;
489  if ((flags == MUTT_PDR_NO_FLAGS) && !have_min)
490  { /* the very first "-3d" without a previous absolute date */
491  max->tm_year = min->tm_year;
492  max->tm_mon = min->tm_mon;
493  max->tm_mday = min->tm_mday;
494  }
495  flags |= MUTT_PDR_MINUS;
496  }
497  break;
498  }
499  case '+':
500  { /* enlarge plus range */
501  pt = get_offset(max, pc, 1);
502  if (pc == pt)
503  flags |= MUTT_PDR_ERRORDONE;
504  else
505  {
506  pc = pt;
507  flags |= MUTT_PDR_PLUS;
508  }
509  break;
510  }
511  case '*':
512  { /* enlarge window in both directions */
513  pt = get_offset(min, pc, -1);
514  if (pc == pt)
515  flags |= MUTT_PDR_ERRORDONE;
516  else
517  {
518  pc = get_offset(max, pc, 1);
519  flags |= MUTT_PDR_WINDOW;
520  }
521  break;
522  }
523  default:
524  flags |= MUTT_PDR_ERRORDONE;
525  }
526  SKIPWS(pc);
527  }
528  if ((flags & MUTT_PDR_ERROR) && !(flags & MUTT_PDR_ABSOLUTE))
529  { /* get_date has its own error message, don't overwrite it here */
530  mutt_buffer_printf(err, _("Invalid relative date: %s"), pc - 1);
531  }
532  return (flags & MUTT_PDR_ERROR) ? NULL : pc;
533 }
#define MUTT_PDR_ABSOLUTE
Absolute pattern range.
Definition: pattern.c:106
#define MUTT_PDR_WINDOW
Extend the range in both directions using &#39;*&#39;.
Definition: pattern.c:105
#define MUTT_PDR_NO_FLAGS
No flags are set.
Definition: pattern.c:102
#define MUTT_PDR_ERROR
Invalid pattern.
Definition: pattern.c:108
#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:191
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:405
static const char * get_offset(struct tm *tm, const char *s, int sign)
Calculate a symbolic offset.
Definition: pattern.c:352
#define MUTT_PDR_PLUS
Extend the range using &#39;+&#39;.
Definition: pattern.c:104
#define SKIPWS(ch)
Definition: string2.h:47
#define MUTT_PDR_MINUS
Pattern contains a range.
Definition: pattern.c:103
#define MUTT_PDR_ERRORDONE
Definition: pattern.c:110
#define MUTT_PDR_DONE
Pattern parse successfully.
Definition: pattern.c:107
uint16_t ParseDateRangeFlags
Flags for parse_date_range(), e.g. MUTT_PDR_MINUS.
Definition: pattern.c:101
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 540 of file pattern.c.

541 {
542  if ((min->tm_year > max->tm_year) ||
543  ((min->tm_year == max->tm_year) && (min->tm_mon > max->tm_mon)) ||
544  ((min->tm_year == max->tm_year) && (min->tm_mon == max->tm_mon) &&
545  (min->tm_mday > max->tm_mday)))
546  {
547  int tmp;
548 
549  tmp = min->tm_year;
550  min->tm_year = max->tm_year;
551  max->tm_year = tmp;
552 
553  tmp = min->tm_mon;
554  min->tm_mon = max->tm_mon;
555  max->tm_mon = tmp;
556 
557  tmp = min->tm_mday;
558  min->tm_mday = max->tm_mday;
559  max->tm_mday = tmp;
560 
561  min->tm_hour = 0;
562  min->tm_min = 0;
563  min->tm_sec = 0;
564  max->tm_hour = 23;
565  max->tm_min = 59;
566  max->tm_sec = 59;
567  }
568 }
static bool eval_date_minmax ( struct Pattern pat,
const char *  s,
struct Buffer err 
)
static

Evaluate a date-range pattern against 'now'.

Parameters
patPattern to modify
sPattern string to use
errBuffer for error messages
Return values
truePattern valid and updated
falsePattern invalid

Definition at line 578 of file pattern.c.

579 {
580  /* the '0' time is Jan 1, 1970 UTC, so in order to prevent a negative time
581  * when doing timezone conversion, we use Jan 2, 1970 UTC as the base here */
582  struct tm min = { 0 };
583  min.tm_mday = 2;
584  min.tm_year = 70;
585 
586  /* Arbitrary year in the future. Don't set this too high or
587  * mutt_date_make_time() returns something larger than will fit in a time_t
588  * on some systems */
589  struct tm max = { 0 };
590  max.tm_year = 130;
591  max.tm_mon = 11;
592  max.tm_mday = 31;
593  max.tm_hour = 23;
594  max.tm_min = 59;
595  max.tm_sec = 59;
596 
597  if (strchr("<>=", s[0]))
598  {
599  /* offset from current time
600  * <3d less than three days ago
601  * >3d more than three days ago
602  * =3d exactly three days ago */
603  struct tm *tm = NULL;
604  bool exact = false;
605 
606  if (s[0] == '<')
607  {
609  tm = &min;
610  }
611  else
612  {
614  tm = &max;
615 
616  if (s[0] == '=')
617  exact = true;
618  }
619 
620  /* Reset the HMS unless we are relative matching using one of those
621  * offsets. */
622  char *offset_type = NULL;
623  strtol(s + 1, &offset_type, 0);
624  if (!(*offset_type && strchr("HMS", *offset_type)))
625  {
626  tm->tm_hour = 23;
627  tm->tm_min = 59;
628  tm->tm_sec = 59;
629  }
630 
631  /* force negative offset */
632  get_offset(tm, s + 1, -1);
633 
634  if (exact)
635  {
636  /* start at the beginning of the day in question */
637  memcpy(&min, &max, sizeof(max));
638  min.tm_hour = 0;
639  min.tm_sec = 0;
640  min.tm_min = 0;
641  }
642  }
643  else
644  {
645  const char *pc = s;
646 
647  bool have_min = false;
648  bool until_now = false;
649  if (isdigit((unsigned char) *pc))
650  {
651  /* minimum date specified */
652  pc = get_date(pc, &min, err);
653  if (!pc)
654  {
655  return false;
656  }
657  have_min = true;
658  SKIPWS(pc);
659  if (*pc == '-')
660  {
661  const char *pt = pc + 1;
662  SKIPWS(pt);
663  until_now = (*pt == '\0');
664  }
665  }
666 
667  if (!until_now)
668  { /* max date or relative range/window */
669 
670  struct tm base_min;
671 
672  if (!have_min)
673  { /* save base minimum and set current date, e.g. for "-3d+1d" */
674  memcpy(&base_min, &min, sizeof(base_min));
676  min.tm_hour = 0;
677  min.tm_sec = 0;
678  min.tm_min = 0;
679  }
680 
681  /* preset max date for relative offsets,
682  * if nothing follows we search for messages on a specific day */
683  max.tm_year = min.tm_year;
684  max.tm_mon = min.tm_mon;
685  max.tm_mday = min.tm_mday;
686 
687  if (!parse_date_range(pc, &min, &max, have_min, &base_min, err))
688  { /* bail out on any parsing error */
689  return false;
690  }
691  }
692  }
693 
694  /* Since we allow two dates to be specified we'll have to adjust that. */
695  adjust_date_range(&min, &max);
696 
697  pat->min = mutt_date_make_time(&min, true);
698  pat->max = mutt_date_make_time(&max, true);
699 
700  return true;
701 }
static void adjust_date_range(struct tm *min, struct tm *max)
Put a date range in the correct order.
Definition: pattern.c:540
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:713
#define MUTT_DATE_NOW
Constant representing the &#39;current time&#39;, see: mutt_date_gmtime(), mutt_date_localtime() ...
Definition: date.h:36
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:405
static const char * get_offset(struct tm *tm, const char *s, int sign)
Calculate a symbolic offset.
Definition: pattern.c:352
#define SKIPWS(ch)
Definition: string2.h:47
int min
Definition: pattern.h:58
int max
Definition: pattern.h:59
time_t mutt_date_make_time(struct tm *t, bool local)
Convert struct tm to time_t
Definition: date.c:223
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:454
static bool eat_range ( struct Pattern pat,
int  flags,
struct Buffer s,
struct Buffer err 
)
static

Parse a number range - Implements pattern_eat_t.

Definition at line 706 of file pattern.c.

707 {
708  char *tmp = NULL;
709  bool do_exclusive = false;
710  bool skip_quote = false;
711 
712  /* If simple_search is set to "~m %s", the range will have double quotes
713  * around it... */
714  if (*s->dptr == '"')
715  {
716  s->dptr++;
717  skip_quote = true;
718  }
719  if (*s->dptr == '<')
720  do_exclusive = true;
721  if ((*s->dptr != '-') && (*s->dptr != '<'))
722  {
723  /* range minimum */
724  if (*s->dptr == '>')
725  {
726  pat->max = MUTT_MAXRANGE;
727  pat->min = strtol(s->dptr + 1, &tmp, 0) + 1; /* exclusive range */
728  }
729  else
730  pat->min = strtol(s->dptr, &tmp, 0);
731  if (toupper((unsigned char) *tmp) == 'K') /* is there a prefix? */
732  {
733  pat->min *= 1024;
734  tmp++;
735  }
736  else if (toupper((unsigned char) *tmp) == 'M')
737  {
738  pat->min *= 1048576;
739  tmp++;
740  }
741  if (*s->dptr == '>')
742  {
743  s->dptr = tmp;
744  return true;
745  }
746  if (*tmp != '-')
747  {
748  /* exact value */
749  pat->max = pat->min;
750  s->dptr = tmp;
751  return true;
752  }
753  tmp++;
754  }
755  else
756  {
757  s->dptr++;
758  tmp = s->dptr;
759  }
760 
761  if (isdigit((unsigned char) *tmp))
762  {
763  /* range maximum */
764  pat->max = strtol(tmp, &tmp, 0);
765  if (toupper((unsigned char) *tmp) == 'K')
766  {
767  pat->max *= 1024;
768  tmp++;
769  }
770  else if (toupper((unsigned char) *tmp) == 'M')
771  {
772  pat->max *= 1048576;
773  tmp++;
774  }
775  if (do_exclusive)
776  (pat->max)--;
777  }
778  else
779  pat->max = MUTT_MAXRANGE;
780 
781  if (skip_quote && (*tmp == '"'))
782  tmp++;
783 
784  SKIPWS(tmp);
785  s->dptr = tmp;
786  return true;
787 }
#define MUTT_MAXRANGE
Definition: pattern.c:99
#define SKIPWS(ch)
Definition: string2.h:47
int min
Definition: pattern.h:58
char * dptr
Current read/write position.
Definition: buffer.h:36
int max
Definition: pattern.h:59
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 796 of file pattern.c.

797 {
798  size_t ds = err->dsize;
799 
800  if (regerror(regerr, preg, err->data, ds) > ds)
801  mutt_debug(LL_DEBUG2, "warning: buffer too small for regerror\n");
802  /* The return value is fixed, exists only to shorten code at callsite */
803  return RANGE_E_SYNTAX;
804 }
Range contains syntax error.
Definition: pattern.c:125
size_t dsize
Length of data.
Definition: buffer.h:37
Log at debug level 2.
Definition: logging.h:57
char * data
Pointer to data.
Definition: buffer.h:35
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
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 815 of file pattern.c.

817 {
818  const char *context_req_chars[] = {
819  [RANGE_K_REL] = ".0123456789",
820  [RANGE_K_ABS] = ".",
821  [RANGE_K_LT] = "",
822  [RANGE_K_GT] = "",
823  [RANGE_K_BARE] = ".",
824  };
825 
826  /* First decide if we're going to need the context at all.
827  * Relative patterns need it if they contain a dot or a number.
828  * Absolute patterns only need it if they contain a dot. */
829  char *context_loc = strpbrk(s->dptr + pmatch[0].rm_so, context_req_chars[kind]);
830  if (!context_loc || (context_loc >= &s->dptr[pmatch[0].rm_eo]))
831  return true;
832 
833  /* We need a current message. Do we actually have one? */
834  if (Context && Context->menu)
835  return true;
836 
837  /* Nope. */
838  mutt_buffer_strcpy(err, _("No current message"));
839  return false;
840 }
The "current" mailbox.
Definition: context.h:39
Single symbol.
Definition: pattern.c:150
#define _(a)
Definition: message.h:28
struct Menu * menu
needed for pattern compilation
Definition: context.h:49
Greater-than range.
Definition: pattern.c:149
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
char * dptr
Current read/write position.
Definition: buffer.h:36
Absolute range.
Definition: pattern.c:147
Less-than range.
Definition: pattern.c:148
Relative range.
Definition: pattern.c:146
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 850 of file pattern.c.

851 {
852  int num = (int) strtol(&s->dptr[pmatch[group].rm_so], NULL, 0);
853  unsigned char c = (unsigned char) (s->dptr[pmatch[group].rm_eo - 1]);
854  if (toupper(c) == 'K')
855  num *= KILO;
856  else if (toupper(c) == 'M')
857  num *= MEGA;
858  switch (kind)
859  {
860  case RANGE_K_REL:
861  return num + CTX_MSGNO(Context);
862  case RANGE_K_LT:
863  return num - 1;
864  case RANGE_K_GT:
865  return num + 1;
866  default:
867  return num;
868  }
869 }
The "current" mailbox.
Definition: context.h:39
#define MEGA
Definition: pattern.c:94
#define KILO
Definition: pattern.c:93
Greater-than range.
Definition: pattern.c:149
char * dptr
Current read/write position.
Definition: buffer.h:36
#define CTX_MSGNO(ctx)
Definition: pattern.c:96
Less-than range.
Definition: pattern.c:148
Relative range.
Definition: pattern.c:146
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 880 of file pattern.c.

881 {
882  /* This means the left or right subpattern was empty, e.g. ",." */
883  if ((pmatch[grp].rm_so == -1) || (pmatch[grp].rm_so == pmatch[grp].rm_eo))
884  {
885  if (side == RANGE_S_LEFT)
886  return 1;
887  else if (side == RANGE_S_RIGHT)
888  return Context->mailbox->msg_count;
889  }
890  /* We have something, so determine what */
891  unsigned char c = (unsigned char) (s->dptr[pmatch[grp].rm_so]);
892  switch (c)
893  {
894  case RANGE_CIRCUM:
895  return 1;
896  case RANGE_DOLLAR:
897  return Context->mailbox->msg_count;
898  case RANGE_DOT:
899  return CTX_MSGNO(Context);
900  case RANGE_LT:
901  case RANGE_GT:
902  return scan_range_num(s, pmatch, grp + 1, kind);
903  default:
904  /* Only other possibility: a number */
905  return scan_range_num(s, pmatch, grp, kind);
906  }
907 }
The "current" mailbox.
Definition: context.h:39
int msg_count
Total number of messages.
Definition: mailbox.h:103
#define RANGE_LT
Definition: pattern.c:115
#define RANGE_DOLLAR
Definition: pattern.c:114
struct Mailbox * mailbox
Definition: context.h:53
static int scan_range_num(struct Buffer *s, regmatch_t pmatch[], int group, int kind)
Parse a number range.
Definition: pattern.c:850
Left side of range.
Definition: pattern.c:160
char * dptr
Current read/write position.
Definition: buffer.h:36
#define RANGE_GT
Definition: pattern.c:116
#define RANGE_CIRCUM
Definition: pattern.c:113
#define CTX_MSGNO(ctx)
Definition: pattern.c:96
#define RANGE_DOT
Definition: pattern.c:112
Right side of range.
Definition: pattern.c:161
static void order_range ( struct Pattern pat)
static

Put a range in order.

Parameters
patPattern to check

Definition at line 913 of file pattern.c.

914 {
915  if (pat->min <= pat->max)
916  return;
917  int num = pat->min;
918  pat->min = pat->max;
919  pat->max = num;
920 }
int min
Definition: pattern.h:58
int max
Definition: pattern.h:59
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 930 of file pattern.c.

932 {
933  int regerr;
934  regmatch_t pmatch[RANGE_RX_GROUPS];
935  struct RangeRegex *pspec = &range_regexes[kind];
936 
937  /* First time through, compile the big regex */
938  if (!pspec->ready)
939  {
940  regerr = regcomp(&pspec->cooked, pspec->raw, REG_EXTENDED);
941  if (regerr != 0)
942  return report_regerror(regerr, &pspec->cooked, err);
943  pspec->ready = true;
944  }
945 
946  /* Match the pattern buffer against the compiled regex.
947  * No match means syntax error. */
948  regerr = regexec(&pspec->cooked, s->dptr, RANGE_RX_GROUPS, pmatch, 0);
949  if (regerr != 0)
950  return report_regerror(regerr, &pspec->cooked, err);
951 
952  if (!is_context_available(s, pmatch, kind, err))
953  return RANGE_E_CTX;
954 
955  /* Snarf the contents of the two sides of the range. */
956  pat->min = scan_range_slot(s, pmatch, pspec->lgrp, RANGE_S_LEFT, kind);
957  pat->max = scan_range_slot(s, pmatch, pspec->rgrp, RANGE_S_RIGHT, kind);
958  mutt_debug(LL_DEBUG1, "pat->min=%d pat->max=%d\n", pat->min, pat->max);
959 
960  /* Special case for a bare 0. */
961  if ((kind == RANGE_K_BARE) && (pat->min == 0) && (pat->max == 0))
962  {
963  if (!Context->menu)
964  {
965  mutt_buffer_strcpy(err, _("No current message"));
966  return RANGE_E_CTX;
967  }
968  pat->max = CTX_MSGNO(Context);
969  pat->min = pat->max;
970  }
971 
972  /* Since we don't enforce order, we must swap bounds if they're backward */
973  order_range(pat);
974 
975  /* Slide pointer past the entire match. */
976  s->dptr += pmatch[0].rm_eo;
977  return RANGE_E_OK;
978 }
The "current" mailbox.
Definition: context.h:39
regex_t cooked
Compiled form.
Definition: pattern.c:138
Single symbol.
Definition: pattern.c:150
Range is valid.
Definition: pattern.c:124
#define _(a)
Definition: message.h:28
Range requires Context, but none available.
Definition: pattern.c:126
struct Menu * menu
needed for pattern compilation
Definition: context.h:49
int min
Definition: pattern.h:58
Left side of range.
Definition: pattern.c:160
Regular expression representing a range.
Definition: pattern.c:132
#define RANGE_RX_GROUPS
Definition: pattern.c:91
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
static struct RangeRegex range_regexes[]
Set of Regexes for various range types.
Definition: pattern.c:192
char * dptr
Current read/write position.
Definition: buffer.h:36
const char * raw
Regex as string.
Definition: pattern.c:134
Log at debug level 1.
Definition: logging.h:56
static void order_range(struct Pattern *pat)
Put a range in order.
Definition: pattern.c:913
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:880
int max
Definition: pattern.h:59
static int report_regerror(int regerr, regex_t *preg, struct Buffer *err)
Create a regex error message.
Definition: pattern.c:796
int lgrp
Paren group matching the left side.
Definition: pattern.c:135
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int rgrp
Paren group matching the right side.
Definition: pattern.c:136
#define CTX_MSGNO(ctx)
Definition: pattern.c:96
bool ready
Compiled yet?
Definition: pattern.c:137
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:815
Right side of range.
Definition: pattern.c:161
static bool eat_message_range ( struct Pattern pat,
int  flags,
struct Buffer s,
struct Buffer err 
)
static

Parse a range of message numbers - Implements pattern_eat_t.

Definition at line 983 of file pattern.c.

985 {
986  bool skip_quote = false;
987 
988  /* We need a Context for pretty much anything. */
989  if (!Context)
990  {
991  mutt_buffer_strcpy(err, _("No Context"));
992  return false;
993  }
994 
995  /* If simple_search is set to "~m %s", the range will have double quotes
996  * around it... */
997  if (*s->dptr == '"')
998  {
999  s->dptr++;
1000  skip_quote = true;
1001  }
1002 
1003  for (int i_kind = 0; i_kind != RANGE_K_INVALID; i_kind++)
1004  {
1005  switch (eat_range_by_regex(pat, s, i_kind, err))
1006  {
1007  case RANGE_E_CTX:
1008  /* This means it matched syntactically but lacked context.
1009  * No point in continuing. */
1010  break;
1011  case RANGE_E_SYNTAX:
1012  /* Try another syntax, then */
1013  continue;
1014  case RANGE_E_OK:
1015  if (skip_quote && (*s->dptr == '"'))
1016  s->dptr++;
1017  SKIPWS(s->dptr);
1018  return true;
1019  }
1020  }
1021  return false;
1022 }
The "current" mailbox.
Definition: context.h:39
Range is valid.
Definition: pattern.c:124
Range contains syntax error.
Definition: pattern.c:125
#define _(a)
Definition: message.h:28
Range requires Context, but none available.
Definition: pattern.c:126
#define SKIPWS(ch)
Definition: string2.h:47
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
char * dptr
Current read/write position.
Definition: buffer.h:36
Range is invalid.
Definition: pattern.c:152
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:930
static bool eat_date ( struct Pattern pat,
int  flags,
struct Buffer s,
struct Buffer err 
)
static

Parse a date pattern - Implements pattern_eat_t.

Definition at line 1027 of file pattern.c.

1028 {
1029  struct Buffer *tmp = mutt_buffer_pool_get();
1030  bool rc = false;
1031 
1032  char *pexpr = s->dptr;
1034  {
1035  snprintf(err->data, err->dsize, _("Error in expression: %s"), pexpr);
1036  goto out;
1037  }
1038 
1039  if (mutt_buffer_is_empty(tmp))
1040  {
1041  snprintf(err->data, err->dsize, "%s", _("Empty expression"));
1042  goto out;
1043  }
1044 
1045  if (flags & MUTT_PATTERN_DYNAMIC)
1046  {
1047  pat->dynamic = true;
1048  pat->p.str = mutt_str_strdup(tmp->data);
1049  }
1050 
1051  rc = eval_date_minmax(pat, tmp->data, err);
1052 
1053 out:
1055 
1056  return rc;
1057 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
#define MUTT_TOKEN_COMMENT
Don&#39;t reap comments.
Definition: mutt.h:82
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
size_t dsize
Length of data.
Definition: buffer.h:37
bool dynamic
evaluate date ranges at run time
Definition: pattern.h:56
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:2614
static bool eval_date_minmax(struct Pattern *pat, const char *s, struct Buffer *err)
Evaluate a date-range pattern against &#39;now&#39;.
Definition: pattern.c:578
char * dptr
Current read/write position.
Definition: buffer.h:36
char * data
Pointer to data.
Definition: buffer.h:35
#define MUTT_PATTERN_DYNAMIC
enable runtime date range evaluation
Definition: pattern.h:42
union Pattern::@2 p
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
char * str
Definition: pattern.h:65
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:283
#define MUTT_TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition: mutt.h:81
static bool patmatch ( const struct Pattern pat,
const char *  buf 
)
static

Compare a string to a Pattern.

Parameters
patPattern to use
bufString to compare
Return values
trueMatch
falseNo match

Definition at line 1066 of file pattern.c.

1067 {
1068  if (pat->ismulti)
1069  return (mutt_list_find(&pat->p.multi_cases, buf) != NULL);
1070  else if (pat->stringmatch)
1071  return pat->ign_case ? strcasestr(buf, pat->p.str) : strstr(buf, pat->p.str);
1072  else if (pat->groupmatch)
1073  return mutt_group_match(pat->p.group, buf);
1074  else
1075  return (regexec(pat->p.regex, buf, 0, NULL, 0) == 0);
1076 }
regex_t * regex
Definition: pattern.h:63
bool mutt_group_match(struct Group *g, const char *s)
Does a string match an entry in a Group?
Definition: group.c:323
struct ListNode * mutt_list_find(const struct ListHead *h, const char *data)
Find a string in a List.
Definition: list.c:103
bool ign_case
ignore case for local stringmatch searches
Definition: pattern.h:54
union Pattern::@2 p
char * str
Definition: pattern.h:65
struct Group * group
Definition: pattern.h:64
bool groupmatch
Definition: pattern.h:53
bool stringmatch
Definition: pattern.h:52
struct ListHead multi_cases
Definition: pattern.h:66
bool ismulti
multiple case (only for I pattern now)
Definition: pattern.h:57
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 1086 of file pattern.c.

1087 {
1088  bool match = false;
1089  struct Message *msg = mx_msg_open(m, msgno);
1090  if (!msg)
1091  {
1092  return match;
1093  }
1094 
1095  FILE *fp = NULL;
1096  long lng = 0;
1097  struct Email *e = m->emails[msgno];
1098 #ifdef USE_FMEMOPEN
1099  char *temp = NULL;
1100  size_t tempsize;
1101 #else
1102  struct stat st;
1103 #endif
1104 
1105  if (C_ThoroughSearch)
1106  {
1107  /* decode the header / body */
1108  struct State s = { 0 };
1109  s.fp_in = msg->fp;
1110  s.flags = MUTT_CHARCONV;
1111 #ifdef USE_FMEMOPEN
1112  s.fp_out = open_memstream(&temp, &tempsize);
1113  if (!s.fp_out)
1114  {
1115  mutt_perror(_("Error opening 'memory stream'"));
1116  return false;
1117  }
1118 #else
1119  s.fp_out = mutt_file_mkstemp();
1120  if (!s.fp_out)
1121  {
1122  mutt_perror(_("Can't create temporary file"));
1123  return false;
1124  }
1125 #endif
1126 
1127  if (pat->op != MUTT_PAT_BODY)
1128  mutt_copy_header(msg->fp, e, s.fp_out, CH_FROM | CH_DECODE, NULL);
1129 
1130  if (pat->op != MUTT_PAT_HEADER)
1131  {
1133 
1134  if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT) &&
1136  {
1137  mx_msg_close(m, &msg);
1138  if (s.fp_out)
1139  {
1141 #ifdef USE_FMEMOPEN
1142  FREE(&temp);
1143 #endif
1144  }
1145  return false;
1146  }
1147 
1148  fseeko(msg->fp, e->offset, SEEK_SET);
1149  mutt_body_handler(e->content, &s);
1150  }
1151 
1152 #ifdef USE_FMEMOPEN
1153  fclose(s.fp_out);
1154  lng = tempsize;
1155 
1156  if (tempsize)
1157  {
1158  fp = fmemopen(temp, tempsize, "r");
1159  if (!fp)
1160  {
1161  mutt_perror(_("Error re-opening 'memory stream'"));
1162  return false;
1163  }
1164  }
1165  else
1166  { /* fmemopen can't handle empty buffers */
1167  fp = mutt_file_fopen("/dev/null", "r");
1168  if (!fp)
1169  {
1170  mutt_perror(_("Error opening /dev/null"));
1171  return false;
1172  }
1173  }
1174 #else
1175  fp = s.fp_out;
1176  fflush(fp);
1177  fseek(fp, 0, SEEK_SET);
1178  fstat(fileno(fp), &st);
1179  lng = (long) st.st_size;
1180 #endif
1181  }
1182  else
1183  {
1184  /* raw header / body */
1185  fp = msg->fp;
1186  if (pat->op != MUTT_PAT_BODY)
1187  {
1188  fseeko(fp, e->offset, SEEK_SET);
1189  lng = e->content->offset - e->offset;
1190  }
1191  if (pat->op != MUTT_PAT_HEADER)
1192  {
1193  if (pat->op == MUTT_PAT_BODY)
1194  fseeko(fp, e->content->offset, SEEK_SET);
1195  lng += e->content->length;
1196  }
1197  }
1198 
1199  size_t blen = 256;
1200  char *buf = mutt_mem_malloc(blen);
1201 
1202  /* search the file "fp" */
1203  while (lng > 0)
1204  {
1205  if (pat->op == MUTT_PAT_HEADER)
1206  {
1207  buf = mutt_rfc822_read_line(fp, buf, &blen);
1208  if (*buf == '\0')
1209  break;
1210  }
1211  else if (!fgets(buf, blen - 1, fp))
1212  break; /* don't loop forever */
1213  if (patmatch(pat, buf))
1214  {
1215  match = true;
1216  break;
1217  }
1218  lng -= mutt_str_strlen(buf);
1219  }
1220 
1221  FREE(&buf);
1222 
1223  mx_msg_close(m, &msg);
1224 
1225  if (C_ThoroughSearch)
1226  {
1227  mutt_file_fclose(&fp);
1228 #ifdef USE_FMEMOPEN
1229  if (tempsize)
1230  FREE(&temp);
1231 #endif
1232  }
1233 
1234  return match;
1235 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
Pattern matches email&#39;s header.
Definition: pattern.h:122
The envelope/body of an email.
Definition: email.h:37
#define mutt_perror(...)
Definition: logging.h:85
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
struct Body * content
List of MIME parts.
Definition: email.h:90
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:50
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define CH_FROM
Retain the "From " message separator?
Definition: copy.h:55
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:121
FILE * fp_in
File to read from.
Definition: state.h:46
int mutt_copy_header(FILE *fp_in, struct Email *e, FILE *fp_out, CopyHeaderFlags chflags, const char *prefix)
Copy Email header.
Definition: copy.c:389
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1092
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:143
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:149
A local copy of an email.
Definition: mx.h:82
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
#define CH_DECODE
Do RFC2047 header decoding.
Definition: copy.h:53
bool C_ThoroughSearch
Config: Decode headers and messages before searching them.
Definition: pattern.c:73
#define mutt_file_mkstemp()
Definition: file.h:105
short op
Definition: pattern.h:49
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:83
Pattern matches email&#39;s body.
Definition: pattern.h:121
FILE * fp
pointer to the message data
Definition: mx.h:84
#define FREE(x)
Definition: memory.h:40
Keep track when processing files.
Definition: state.h:44
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1544
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:584
#define WithCrypto
Definition: ncrypt.h:156
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1044
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:1066
int msgno
Number displayed to the user.
Definition: email.h:86
char * mutt_rfc822_read_line(FILE *fp, char *line, size_t *linelen)
Read a header line from a file.
Definition: parse.c:949
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 1301 of file pattern.c.

1302 {
1303  for (int i = 0; Flags[i].tag; i++)
1304  if (Flags[i].tag == tag)
1305  return &Flags[i];
1306  return NULL;
1307 }
int tag
character used to represent this op
Definition: pattern.c:180
static const struct PatternFlags Flags[]
Lookup table for all patterns.
Definition: pattern.c:1241
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 1315 of file pattern.c.

1316 {
1317  int level = 1;
1318 
1319  for (; *s; s++)
1320  {
1321  if (*s == '(')
1322  level++;
1323  else if (*s == ')')
1324  {
1325  level--;
1326  if (level == 0)
1327  break;
1328  }
1329  }
1330  return s;
1331 }
void mutt_pattern_free ( struct PatternHead **  pat)

Free a Pattern.

Parameters
[out]patPattern to free

Definition at line 1337 of file pattern.c.

1338 {
1339  if (!pat || !*pat)
1340  return;
1341 
1342  struct Pattern *np = SLIST_FIRST(*pat), *next = NULL;
1343 
1344  while (np)
1345  {
1346  next = SLIST_NEXT(np, entries);
1347 
1348  if (np->ismulti)
1350  else if (np->stringmatch || np->dynamic)
1351  FREE(&np->p.str);
1352  else if (np->groupmatch)
1353  np->p.group = NULL;
1354  else if (np->p.regex)
1355  {
1356  regfree(np->p.regex);
1357  FREE(&np->p.regex);
1358  }
1359 
1360  mutt_pattern_free(&np->child);
1361  FREE(&np);
1362 
1363  np = next;
1364  }
1365 
1366  FREE(pat);
1367 }
regex_t * regex
Definition: pattern.h:63
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:123
A simple (non-regex) pattern.
Definition: pattern.h:47
bool dynamic
evaluate date ranges at run time
Definition: pattern.h:56
#define SLIST_NEXT(elm, field)
Definition: queue.h:270
#define SLIST_FIRST(head)
Definition: queue.h:229
union Pattern::@2 p
struct PatternHead * child
arguments to logical op
Definition: pattern.h:61
char * str
Definition: pattern.h:65
struct Group * group
Definition: pattern.h:64
#define FREE(x)
Definition: memory.h:40
bool groupmatch
Definition: pattern.h:53
bool stringmatch
Definition: pattern.h:52
struct ListHead multi_cases
Definition: pattern.h:66
bool ismulti
multiple case (only for I pattern now)
Definition: pattern.h:57
void mutt_pattern_free(struct PatternHead **pat)
Free a Pattern.
Definition: pattern.c:1337
static struct PatternHead* mutt_pattern_node_new ( void  )
static

Create a new list containing a Pattern.

Return values
ptrNewly created list containing a single node with a Pattern

Definition at line 1373 of file pattern.c.

1374 {
1375  struct PatternHead *h = mutt_mem_calloc(1, sizeof(struct PatternHead));
1376  SLIST_INIT(h);
1377  struct Pattern *p = mutt_mem_calloc(1, sizeof(struct Pattern));
1378  SLIST_INSERT_HEAD(h, p, entries);
1379  return h;
1380 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define SLIST_INIT(head)
Definition: queue.h:256
A simple (non-regex) pattern.
Definition: pattern.h:47
union Pattern::@2 p
#define SLIST_INSERT_HEAD(head, elm, field)
Definition: queue.h:265
struct PatternHead* mutt_pattern_comp ( const 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 1389 of file pattern.c.

1390 {
1391  /* curlist when assigned will always point to a list containing at least one node
1392  * with a Pattern value. */
1393  struct PatternHead *curlist = NULL;
1394  struct PatternHead *tmp = NULL, *tmp2 = NULL;
1395  struct PatternHead *last = NULL;
1396  bool pat_not = false;
1397  bool alladdr = false;
1398  bool pat_or = false;
1399  bool implicit = true; /* used to detect logical AND operator */
1400  bool isalias = false;
1401  short thread_op;
1402  const struct PatternFlags *entry = NULL;
1403  char *p = NULL;
1404  char *buf = NULL;
1405  struct Buffer ps;
1406 
1407  mutt_buffer_init(&ps);
1408  ps.dptr = (char *) s;
1409  ps.dsize = mutt_str_strlen(s);
1410 
1411  while (*ps.dptr)
1412  {
1413  SKIPWS(ps.dptr);
1414  switch (*ps.dptr)
1415  {
1416  case '^':
1417  ps.dptr++;
1418  alladdr = !alladdr;
1419  break;
1420  case '!':
1421  ps.dptr++;
1422  pat_not = !pat_not;
1423  break;
1424  case '@':
1425  ps.dptr++;
1426  isalias = !isalias;
1427  break;
1428  case '|':
1429  if (!pat_or)
1430  {
1431  if (!curlist)
1432  {
1433  mutt_buffer_printf(err, _("error in pattern at: %s"), ps.dptr);
1434  return NULL;
1435  }
1436 
1437  struct Pattern *pat = SLIST_FIRST(curlist);
1438 
1439  if (SLIST_NEXT(pat, entries))
1440  {
1441  /* A & B | C == (A & B) | C */
1442  tmp = mutt_pattern_node_new();
1443  pat = SLIST_FIRST(tmp);
1444  pat->op = MUTT_PAT_AND;
1445  pat->child = curlist;
1446 
1447  curlist = tmp;
1448  last = curlist;
1449  }
1450 
1451  pat_or = true;
1452  }
1453  ps.dptr++;
1454  implicit = false;
1455  pat_not = false;
1456  alladdr = false;
1457  isalias = false;
1458  break;
1459  case '%':
1460  case '=':
1461  case '~':
1462  {
1463  struct Pattern *pat = NULL;
1464  if (ps.dptr[1] == '\0')
1465  {
1466  mutt_buffer_printf(err, _("missing pattern: %s"), ps.dptr);
1467  goto cleanup;
1468  }
1469  thread_op = 0;
1470  if (ps.dptr[1] == '(')
1471  thread_op = MUTT_PAT_THREAD;
1472  else if ((ps.dptr[1] == '<') && (ps.dptr[2] == '('))
1473  thread_op = MUTT_PAT_PARENT;
1474  else if ((ps.dptr[1] == '>') && (ps.dptr[2] == '('))
1475  thread_op = MUTT_PAT_CHILDREN;
1476  if (thread_op)
1477  {
1478  ps.dptr++; /* skip ~ */
1479  if ((thread_op == MUTT_PAT_PARENT) || (thread_op == MUTT_PAT_CHILDREN))
1480  ps.dptr++;
1481  p = find_matching_paren(ps.dptr + 1);
1482  if (p[0] != ')')
1483  {
1484  mutt_buffer_printf(err, _("mismatched parentheses: %s"), ps.dptr);
1485  goto cleanup;
1486  }
1487  tmp = mutt_pattern_node_new();
1488  pat = SLIST_FIRST(tmp);
1489  pat->op = thread_op;
1490  if (last)
1491  SLIST_NEXT(SLIST_FIRST(last), entries) = pat;
1492  else
1493  curlist = tmp;
1494  last = tmp;
1495  pat->pat_not ^= pat_not;
1496  pat->alladdr |= alladdr;
1497  pat->isalias |= isalias;
1498  pat_not = false;
1499  alladdr = false;
1500  isalias = false;
1501  /* compile the sub-expression */
1502  buf = mutt_str_substr_dup(ps.dptr + 1, p);
1503  tmp2 = mutt_pattern_comp(buf, flags, err);
1504  if (!tmp2)
1505  {
1506  FREE(&buf);
1507  goto cleanup;
1508  }
1509  FREE(&buf);
1510  pat->child = tmp2;
1511  ps.dptr = p + 1; /* restore location */
1512  break;
1513  }
1514  if (implicit && pat_or)
1515  {
1516  /* A | B & C == (A | B) & C */
1517  tmp = mutt_pattern_node_new();
1518  pat = SLIST_FIRST(tmp);
1519  pat->op = MUTT_PAT_OR;
1520  pat->child = curlist;
1521  curlist = tmp;
1522  last = tmp;
1523  pat_or = false;
1524  }
1525 
1526  tmp = mutt_pattern_node_new();
1527  pat = SLIST_FIRST(tmp);
1528  pat->pat_not = pat_not;
1529  pat->alladdr = alladdr;
1530  pat->isalias = isalias;
1531  pat->stringmatch = (ps.dptr[0] == '=');
1532  pat->groupmatch = (ps.dptr[0] == '%');
1533  pat_not = false;
1534  alladdr = false;
1535  isalias = false;
1536 
1537  if (last)
1538  SLIST_NEXT(SLIST_FIRST(last), entries) = pat;
1539  else
1540  curlist = tmp;
1541  if (curlist != last)
1542  FREE(&last);
1543  last = tmp;
1544 
1545  ps.dptr++; /* move past the ~ */
1546  entry = lookup_tag(*ps.dptr);
1547  if (!entry)
1548  {
1549  mutt_buffer_printf(err, _("%c: invalid pattern modifier"), *ps.dptr);
1550  goto cleanup;
1551  }
1552  if (entry->flags && ((flags & entry->flags) == 0))
1553  {
1554  mutt_buffer_printf(err, _("%c: not supported in this mode"), *ps.dptr);
1555  goto cleanup;
1556  }
1557  pat->op = entry->op;
1558 
1559  ps.dptr++; /* eat the operator and any optional whitespace */
1560  SKIPWS(ps.dptr);
1561 
1562  if (entry->eat_arg)
1563  {
1564  if (ps.dptr[0] == '\0')
1565  {
1566  mutt_buffer_printf(err, "%s", _("missing parameter"));
1567  goto cleanup;
1568  }
1569  if (!entry->eat_arg(pat, flags, &ps, err))
1570  {
1571  goto cleanup;
1572  }
1573  }
1574  implicit = true;
1575  break;
1576  }
1577 
1578  case '(':
1579  {
1580  p = find_matching_paren(ps.dptr + 1);
1581  if (p[0] != ')')
1582  {
1583  mutt_buffer_printf(err, _("mismatched parentheses: %s"), ps.dptr);
1584  goto cleanup;
1585  }
1586  /* compile the sub-expression */
1587  buf = mutt_str_substr_dup(ps.dptr + 1, p);
1588  tmp = mutt_pattern_comp(buf, flags, err);
1589  FREE(&buf);
1590  if (!tmp)
1591  goto cleanup;
1592  struct Pattern *pat = SLIST_FIRST(tmp);
1593  if (last)
1594  SLIST_NEXT(SLIST_FIRST(last), entries) = pat;
1595  else
1596  curlist = tmp;
1597  last = tmp;
1598  pat = SLIST_FIRST(tmp);
1599  pat->pat_not ^= pat_not;
1600  pat->alladdr |= alladdr;
1601  pat->isalias |= isalias;
1602  pat_not = false;
1603  alladdr = false;
1604  isalias = false;
1605  ps.dptr = p + 1; /* restore location */
1606  break;
1607  }
1608 
1609  default:
1610  mutt_buffer_printf(err, _("error in pattern at: %s"), ps.dptr);
1611  goto cleanup;
1612  }
1613  }
1614  if (!curlist)
1615  {
1616  mutt_buffer_strcpy(err, _("empty pattern"));
1617  return NULL;
1618  }
1619  if (curlist != tmp)
1620  FREE(&tmp);
1621  if (SLIST_NEXT(SLIST_FIRST(curlist), entries))
1622  {
1623  tmp = mutt_pattern_node_new();
1624  struct Pattern *pat = SLIST_FIRST(tmp);
1625  pat->op = pat_or ? MUTT_PAT_OR : MUTT_PAT_AND;
1626  pat->child = curlist;
1627  curlist = tmp;
1628  }
1629 
1630  return curlist;
1631 
1632 cleanup:
1633  mutt_pattern_free(&curlist);
1634  return NULL;
1635 }
pattern_eat_t * eat_arg
Callback function to parse the argument.
Definition: pattern.c:183
int flags
Pattern flags, e.g. MUTT_FULL_MSG.
Definition: pattern.c:182
struct PatternHead * mutt_pattern_comp(const char *s, int flags, struct Buffer *err)
Create a Pattern.
Definition: pattern.c:1389
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
static char * find_matching_paren(char *s)
Find the matching parenthesis.
Definition: pattern.c:1315
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:666
Pattern matches a child email.
Definition: pattern.h:108
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:191
A simple (non-regex) pattern.
Definition: pattern.h:47
int op
operation to perform
Definition: pattern.c:181
static const struct PatternFlags * lookup_tag(char tag)
Lookup a pattern modifier.
Definition: pattern.c:1301
#define SKIPWS(ch)
Definition: string2.h:47
bool pat_not
Definition: pattern.h:50
#define SLIST_NEXT(elm, field)
Definition: queue.h:270
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
static struct PatternHead * mutt_pattern_node_new(void)
Create a new list containing a Pattern.
Definition: pattern.c:1373
#define SLIST_FIRST(head)
Definition: queue.h:229
Either pattern can match.
Definition: pattern.h:105
short op
Definition: pattern.h:49
Pattern matches parent.
Definition: pattern.h:107
bool isalias
Definition: pattern.h:55
struct PatternHead * child
arguments to logical op
Definition: pattern.h:61
Both patterns must match.
Definition: pattern.h:104
#define FREE(x)
Definition: memory.h:40
bool groupmatch
Definition: pattern.h:53
bool stringmatch
Definition: pattern.h:52
bool alladdr
Definition: pattern.h:51
Pattern matches email thread.
Definition: pattern.h:106
Mapping between user character and internal constant.
Definition: pattern.c:178
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:61
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:579
void mutt_pattern_free(struct PatternHead **pat)
Free a Pattern.
Definition: pattern.c:1337
static bool perform_and ( struct PatternHead *  pat,
PatternExecFlags  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 1646 of file pattern.c.

1648 {
1649  struct Pattern *p = NULL;
1650 
1651  SLIST_FOREACH(p, pat, entries)
1652  {
1653  if (mutt_pattern_exec(p, flags, m, e, cache) <= 0)
1654  return false;
1655  }
1656  return true;
1657 }
A simple (non-regex) pattern.
Definition: pattern.h:47
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2005
union Pattern::@2 p
#define SLIST_FOREACH(var, head, field)
Definition: queue.h:231
static int perform_or ( struct PatternHead *  pat,
PatternExecFlags  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 1668 of file pattern.c.

1670 {
1671  struct Pattern *p = NULL;
1672 
1673  SLIST_FOREACH(p, pat, entries)
1674  {
1675  if (mutt_pattern_exec(p, flags, m, e, cache) > 0)
1676  return true;
1677  }
1678  return false;
1679 }
A simple (non-regex) pattern.
Definition: pattern.h:47
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2005
union Pattern::@2 p
#define SLIST_FOREACH(var, head, field)
Definition: queue.h:231
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 1690 of file pattern.c.

1691 {
1692  va_list ap;
1693 
1694  va_start(ap, n);
1695  for (; n; n--)
1696  {
1697  struct AddressList *al = va_arg(ap, struct AddressList *);
1698  struct Address *a = NULL;
1699  TAILQ_FOREACH(a, al, entries)
1700  {
1701  if (pat->alladdr ^ ((!pat->isalias || mutt_alias_reverse_lookup(a)) &&
1702  ((a->mailbox && patmatch(pat, a->mailbox)) ||
1703  (match_personal && a->personal && patmatch(pat, a->personal)))))
1704  {
1705  va_end(ap);
1706  return !pat->alladdr; /* Found match, or non-match if alladdr */
1707  }
1708  }
1709  }
1710  va_end(ap);
1711  return pat->alladdr; /* No matches, or all matches if alladdr */
1712 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
An email address.
Definition: address.h:34
char * mailbox
Mailbox and host address.
Definition: address.h:37
struct Address * mutt_alias_reverse_lookup(const struct Address *a)
Does the user have an alias for the given address.
Definition: alias.c:528
char * personal
Real name of address.
Definition: address.h:36
bool isalias
Definition: pattern.h:55
bool alladdr
Definition: pattern.h:51
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:1066
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 1720 of file pattern.c.

1721 {
1722  struct ListNode *np = NULL;
1723  STAILQ_FOREACH(np, refs, entries)
1724  {
1725  if (patmatch(pat, np->data))
1726  return true;
1727  }
1728  return false;
1729 }
#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
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:1066
static int mutt_is_predicate_recipient ( bool  alladdr,
struct Envelope e,
addr_predicate_t  p 
)
static

Test an Envelopes Addresses using a predicate function.

Parameters
alladdrIf true, ALL Addresses must match
eEnvelope
pPredicate function, e.g. mutt_is_subscribed_list()
Return values
trueOne Address matches (alladdr is false)
trueAll the Addresses match (alladdr is true)

Test the 'To' and 'Cc' fields of an Address using a test function (the predicate).

Definition at line 1748 of file pattern.c.

1749 {
1750  struct AddressList *als[] = { &e->to, &e->cc };
1751  for (size_t i = 0; i < mutt_array_size(als); ++i)
1752  {
1753  struct AddressList *al = als[i];
1754  struct Address *a = NULL;
1755  TAILQ_FOREACH(a, al, entries)
1756  {
1757  if (alladdr ^ p(a))
1758  return !alladdr;
1759  }
1760  }
1761  return alladdr;
1762 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
An email address.
Definition: address.h:34
#define mutt_array_size(x)
Definition: memory.h:33
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:45
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:44
int mutt_is_subscribed_list_recipient ( bool  alladdr,
struct Envelope e 
)

Matches subscribed mailing lists.

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

Definition at line 1771 of file pattern.c.

1772 {
1774 }
bool mutt_is_subscribed_list(const struct Address *addr)
Is this the email address of a user-subscribed mailing list?
Definition: hdrline.c:114
static int mutt_is_predicate_recipient(bool alladdr, struct Envelope *e, addr_predicate_t p)
Test an Envelopes Addresses using a predicate function.
Definition: pattern.c:1748
int mutt_is_list_recipient ( bool  alladdr,
struct Envelope e 
)

Matches known mailing lists.

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

Definition at line 1783 of file pattern.c.

1784 {
1785  return mutt_is_predicate_recipient(alladdr, e, &mutt_is_mail_list);
1786 }
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:102
static int mutt_is_predicate_recipient(bool alladdr, struct Envelope *e, addr_predicate_t p)
Test an Envelopes Addresses using a predicate function.
Definition: pattern.c:1748
static int match_user ( int  alladdr,
struct AddressList *  al1,
struct AddressList *  al2 
)
static

Matches the user's email Address.

Parameters
alladdrIf true, ALL Addresses must refer to the user
al1First AddressList
al2Second AddressList
Return values
trueOne Address refers to the user (alladdr is false)
trueAll the Addresses refer to the user (alladdr is true)

Definition at line 1796 of file pattern.c.

1797 {
1798  struct Address *a = NULL;
1799  if (al1)
1800  {
1801  TAILQ_FOREACH(a, al1, entries)
1802  {
1803  if (alladdr ^ mutt_addr_is_user(a))
1804  return !alladdr;
1805  }
1806  }
1807 
1808  if (al2)
1809  {
1810  TAILQ_FOREACH(a, al2, entries)
1811  {
1812  if (alladdr ^ mutt_addr_is_user(a))
1813  return !alladdr;
1814  }
1815  }
1816  return alladdr;
1817 }
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:719
An email address.
Definition: address.h:34
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:669
static int match_threadcomplete ( struct PatternHead *  pat,
PatternExecFlags  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 1832 of file pattern.c.

1835 {
1836  if (!t)
1837  return 0;
1838 
1839  int a;
1840  struct Email *e = t->message;
1841  if (e)
1842  if (mutt_pattern_exec(SLIST_FIRST(pat), flags, m, e, NULL))
1843  return 1;
1844 
1845  if (up && (a = match_threadcomplete(pat, flags, m, t->parent, 1, 1, 1, 0)))
1846  return a;
1847  if (right && t->parent && (a = match_threadcomplete(pat, flags, m, t->next, 0, 0, 1, 1)))
1848  {
1849  return a;
1850  }
1851  if (left && t->parent && (a = match_threadcomplete(pat, flags, m, t->prev, 1, 0, 0, 1)))
1852  {
1853  return a;
1854  }
1855  if (down && (a = match_threadcomplete(pat, flags, m, t->child, 1, 0, 1, 1)))
1856  return a;
1857  return 0;
1858 }
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
The envelope/body of an email.
Definition: email.h:37
static int match_threadcomplete(struct PatternHead *pat, PatternExecFlags 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:1832
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
struct MuttThread * prev
Previous sibling Thread.
Definition: thread.h:48
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2005
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
#define SLIST_FIRST(head)
Definition: queue.h:229
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
static int match_threadparent ( struct PatternHead *  pat,
PatternExecFlags  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 1870 of file pattern.c.

1872 {
1873  if (!t || !t->parent || !t->parent->message)
1874  return 0;
1875 
1876  return mutt_pattern_exec(SLIST_FIRST(pat), flags, m, t->parent->message, NULL);
1877 }
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2005
#define SLIST_FIRST(head)
Definition: queue.h:229
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
static int match_threadchildren ( struct PatternHead *  pat,
PatternExecFlags  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 1889 of file pattern.c.

1891 {
1892  if (!t || !t->child)
1893  return 0;
1894 
1895  for (t = t->child; t; t = t->next)
1896  if (t->message && mutt_pattern_exec(SLIST_FIRST(pat), flags, m, t->message, NULL))
1897  return 1;
1898 
1899  return 0;
1900 }
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2005
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
#define SLIST_FIRST(head)
Definition: queue.h:229
struct Email * message
Email this Thread refers to.
Definition: thread.h:49
static bool 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
trueSuccess, pattern matched
falsePattern did not match

Definition at line 1909 of file pattern.c.

1910 {
1911  if (!b)
1912  return false;
1913 
1914  char buf[256];
1915  snprintf(buf, sizeof(buf), "%s/%s", TYPE(b), b->subtype);
1916 
1917  if (patmatch(pat, buf))
1918  return true;
1919  if (match_content_type(pat, b->parts))
1920  return true;
1921  if (match_content_type(pat, b->next))
1922  return true;
1923  return false;
1924 }
struct Body * next
next attachment in the list
Definition: body.h:53
char * subtype
content-type subtype
Definition: body.h:37
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
#define TYPE(body)
Definition: mime.h:83
static bool match_content_type(const struct Pattern *pat, struct Body *b)
Match a Pattern against an Attachment&#39;s Content-Type.
Definition: pattern.c:1909
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:1066
static bool match_update_dynamic_date ( struct Pattern pat)
static

Update a dynamic date pattern.

Parameters
patPattern to modify
Return values
truePattern valid and updated
falsePattern invalid

Definition at line 1932 of file pattern.c.

1933 {
1934  struct Buffer *err = mutt_buffer_pool_get();
1935 
1936  bool rc = eval_date_minmax(pat, pat->p.str, err);
1938 
1939  return rc;
1940 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
String manipulation buffer.
Definition: buffer.h:33
static bool eval_date_minmax(struct Pattern *pat, const char *s, struct Buffer *err)
Evaluate a date-range pattern against &#39;now&#39;.
Definition: pattern.c:578
union Pattern::@2 p
char * str
Definition: pattern.h:65
static bool 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
trueSuccess, pattern matched
falsePattern did not match

Definition at line 1950 of file pattern.c.

1952 {
1954  return match_content_type(pat, e->content);
1955 }
struct Body * content
List of MIME parts.
Definition: email.h:90
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:50
static bool match_content_type(const struct Pattern *pat, struct Body *b)
Match a Pattern against an Attachment&#39;s Content-Type.
Definition: pattern.c:1909
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 1964 of file pattern.c.

1965 {
1966  *cache_entry = (value != 0) ? 2 : 1;
1967 }
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 1975 of file pattern.c.

1976 {
1977  return cache_entry == 2;
1978 }
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 1985 of file pattern.c.

1986 {
1987  return cache_entry != 0;
1988 }
int mutt_pattern_exec ( struct Pattern pat,
PatternExecFlags  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 2005 of file pattern.c.

2007 {
2008  switch (pat->op)
2009  {
2010  case MUTT_PAT_AND:
2011  return pat->pat_not ^ (perform_and(pat->child, flags, m, e, cache) > 0);
2012  case MUTT_PAT_OR:
2013  return pat->pat_not ^ (perform_or(pat->child, flags, m, e, cache) > 0);
2014  case MUTT_PAT_THREAD:
2015  return pat->pat_not ^
2016  match_threadcomplete(pat->child, flags, m, e->thread, 1, 1, 1, 1);
2017  case MUTT_PAT_PARENT:
2018  return pat->pat_not ^ match_threadparent(pat->child, flags, m, e->thread);
2019  case MUTT_PAT_CHILDREN:
2020  return pat->pat_not ^ match_threadchildren(pat->child, flags, m, e->thread);
2021  case MUTT_ALL:
2022  return !pat->pat_not;
2023  case MUTT_EXPIRED:
2024  return pat->pat_not ^ e->expired;
2025  case MUTT_SUPERSEDED:
2026  return pat->pat_not ^ e->superseded;
2027  case MUTT_FLAG:
2028  return pat->pat_not ^ e->flagged;
2029  case MUTT_TAG:
2030  return pat->pat_not ^ e->tagged;
2031  case MUTT_NEW:
2032  return pat->pat_not ? e->old || e->read : !(e->old || e->read);
2033  case MUTT_UNREAD:
2034  return pat->pat_not ? e->read : !e->read;
2035  case MUTT_REPLIED:
2036  return pat->pat_not ^ e->replied;
2037  case MUTT_OLD:
2038  return pat->pat_not ? (!e->old || e->read) : (e->old && !e->read);
2039  case MUTT_READ:
2040  return pat->pat_not ^ e->read;
2041  case MUTT_DELETED:
2042  return pat->pat_not ^ e->deleted;
2043  case MUTT_PAT_MESSAGE:
2044  return pat->pat_not ^ ((EMSG(e) >= pat->min) && (EMSG(e) <= pat->max));
2045  case MUTT_PAT_DATE:
2046  if (pat->dynamic)
2048  return pat->pat_not ^ (e->date_sent >= pat->min && e->date_sent <= pat->max);
2050  if (pat->dynamic)
2052  return pat->pat_not ^ (e->received >= pat->min && e->received <= pat->max);
2053  case MUTT_PAT_BODY:
2054  case MUTT_PAT_HEADER:
2055  case MUTT_PAT_WHOLE_MSG:
2056  /* m can be NULL in certain cases, such as when replying to a message
2057  * from the attachment menu and the user has a reply-hook using "~e" (bug
2058  * #2190).
2059  * This is also the case when message scoring. */
2060  if (!m)
2061  return 0;
2062 #ifdef USE_IMAP
2063  /* IMAP search sets e->matched at search compile time */
2064  if ((m->magic == MUTT_IMAP) && pat->stringmatch)
2065  return e->matched;
2066 #endif
2067  return pat->pat_not ^ msg_search(m, pat, e->msgno);
2068  case MUTT_PAT_SERVERSEARCH:
2069 #ifdef USE_IMAP
2070  if (!m)
2071  return 0;
2072  if (m->magic == MUTT_IMAP)
2073  {
2074  if (pat->stringmatch)
2075  return e->matched;
2076  return 0;
2077  }
2078  mutt_error(_("error: server custom search only supported with IMAP"));
2079  return 0;
2080 #else
2081  mutt_error(_("error: server custom search only supported with IMAP"));
2082  return -1;
2083 #endif
2084  case MUTT_PAT_SENDER:
2085  if (!e->env)
2086  return 0;
2087  return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
2088  1, &e->env->sender);
2089  case MUTT_PAT_FROM:
2090  if (!e->env)
2091  return 0;
2092  return pat->pat_not ^
2093  match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->from);
2094  case MUTT_PAT_TO:
2095  if (!e->env)
2096  return 0;
2097  return pat->pat_not ^
2098  match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->to);
2099  case MUTT_PAT_CC:
2100  if (!e->env)
2101  return 0;
2102  return pat->pat_not ^
2103  match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1, &e->env->cc);
2104  case MUTT_PAT_SUBJECT:
2105  if (!e->env)
2106  return 0;
2107  return pat->pat_not ^ (e->env->subject && patmatch(pat, e->env->subject));
2108  case MUTT_PAT_ID:
2109  case MUTT_PAT_ID_EXTERNAL:
2110  if (!e->env)
2111  return 0;
2112  return pat->pat_not ^ (e->env->message_id && patmatch(pat, e->env->message_id));
2113  case MUTT_PAT_SCORE:
2114  return pat->pat_not ^ (e->score >= pat->min &&
2115  (pat->max == MUTT_MAXRANGE || e->score <= pat->max));
2116  case MUTT_PAT_SIZE:
2117  return pat->pat_not ^
2118  (e->content->length >= pat->min &&
2119  (pat->max == MUTT_MAXRANGE || e->content->length <= pat->max));
2120  case MUTT_PAT_REFERENCE:
2121  if (!e->env)
2122  return 0;
2123  return pat->pat_not ^ (match_reference(pat, &e->env->references) ||
2124  match_reference(pat, &e->env->in_reply_to));
2125  case MUTT_PAT_ADDRESS:
2126  if (!e->env)
2127  return 0;
2128  return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
2129  4, &e->env->from, &e->env->sender,
2130  &e->env->to, &e->env->cc);
2131  case MUTT_PAT_RECIPIENT:
2132  if (!e->env)
2133  return 0;
2134  return pat->pat_not ^ match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS),
2135  2, &e->env->to, &e->env->cc);
2136  case MUTT_PAT_LIST: /* known list, subscribed or not */
2137  {
2138  if (!e->env)
2139  return 0;
2140 
2141  int result;
2142  if (cache)
2143  {
2144  int *cache_entry = pat->alladdr ? &cache->list_all : &cache->list_one;
2145  if (!is_pattern_cache_set(*cache_entry))
2146  {
2147  set_pattern_cache_value(cache_entry,
2148  mutt_is_list_recipient(pat->alladdr, e->env));
2149  }
2150  result = get_pattern_cache_value(*cache_entry);
2151  }
2152  else
2153  result = mutt_is_list_recipient(pat->alladdr, e->env);
2154  return pat->pat_not ^ result;
2155  }
2157  {
2158  if (!e->env)
2159  return 0;
2160 
2161  int result;
2162  if (cache)
2163  {
2164  int *cache_entry = pat->alladdr ? &cache->sub_all : &cache->sub_one;
2165  if (!is_pattern_cache_set(*cache_entry))
2166  {
2168  cache_entry, mutt_is_subscribed_list_recipient(pat->alladdr, e->env));
2169  }
2170  result = get_pattern_cache_value(*cache_entry);
2171  }
2172  else
2173  result = mutt_is_subscribed_list_recipient(pat->alladdr, e->env);
2174  return pat->pat_not ^ result;
2175  }
2177  {
2178  if (!e->env)
2179  return 0;
2180 
2181  int result;
2182  if (cache)
2183  {
2184  int *cache_entry = pat->alladdr ? &cache->pers_recip_all : &cache->pers_recip_one;
2185  if (!is_pattern_cache_set(*cache_entry))
2186  {
2188  cache_entry, match_user(pat->alladdr, &e->env->to, &e->env->cc));
2189  }
2190  result = get_pattern_cache_value(*cache_entry);
2191  }
2192  else
2193  result = match_user(pat->alladdr, &e->env->to, &e->env->cc);
2194  return pat->pat_not ^ result;
2195  }
2197  {
2198  if (!e->env)
2199  return 0;
2200 
2201  int result;
2202  if (cache)
2203  {
2204  int *cache_entry = pat->alladdr ? &cache->pers_from_all : &cache->pers_from_one;
2205  if (!is_pattern_cache_set(*cache_entry))
2206  set_pattern_cache_value(cache_entry,
2207  match_user(pat->alladdr, &e->env->from, NULL));
2208  result = get_pattern_cache_value(*cache_entry);
2209  }
2210  else
2211  result = match_user(pat->alladdr, &e->env->from, NULL);
2212  return pat->pat_not ^ result;
2213  }
2214  case MUTT_PAT_COLLAPSED:
2215  return pat->pat_not ^ (e->collapsed && e->num_hidden > 1);
2216  case MUTT_PAT_CRYPT_SIGN:
2217  if (!WithCrypto)
2218  break;
2219  return pat->pat_not ^ ((e->security & SEC_SIGN) ? 1 : 0);
2221  if (!WithCrypto)
2222  break;
2223  return pat->pat_not ^ ((e->security & SEC_GOODSIGN) ? 1 : 0);
2225  if (!WithCrypto)
2226  break;
2227  return pat->pat_not ^ ((e->security & SEC_ENCRYPT) ? 1 : 0);
2228  case MUTT_PAT_PGP_KEY:
2229  if (!(WithCrypto & APPLICATION_PGP))
2230  break;
2231  return pat->pat_not ^ ((e->security & PGP_KEY) == PGP_KEY);
2232  case MUTT_PAT_XLABEL:
2233  if (!e->env)
2234  return 0;
2235  return pat->pat_not ^ (e->env->x_label && patmatch(pat, e->env->x_label));
2236  case MUTT_PAT_DRIVER_TAGS:
2237  {
2238  char *tags = driver_tags_get(&e->tags);
2239  bool rc = (pat->pat_not ^ (tags && patmatch(pat, tags)));
2240  FREE(&tags);
2241  return rc;
2242  }
2243  case MUTT_PAT_HORMEL:
2244  if (!e->env)
2245  return 0;
2246  return pat->pat_not ^ (e->env->spam && e->env->spam->data &&
2247  patmatch(pat, e->env->spam->data));
2248  case MUTT_PAT_DUPLICATED:
2249  return pat->pat_not ^ (e->thread && e->thread->duplicate_thread);
2250  case MUTT_PAT_MIMEATTACH:
2251  if (!m)
2252  return 0;
2253  {
2254  int count = mutt_count_body_parts(m, e);
2255  return pat->pat_not ^ (count >= pat->min &&
2256  (pat->max == MUTT_MAXRANGE || count <= pat->max));
2257  }
2258  case MUTT_PAT_MIMETYPE:
2259  if (!m)
2260  return 0;
2261  return pat->pat_not ^ match_mime_content_type(pat, m, e);
2262  case MUTT_PAT_UNREFERENCED:
2263  return pat->pat_not ^ (e->thread && !e->thread->child);
2264  case MUTT_PAT_BROKEN:
2265  return pat->pat_not ^ (e->thread && e->thread->fake_thread);
2266 #ifdef USE_NNTP
2267  case MUTT_PAT_NEWSGROUPS:
2268  if (!e->env)
2269  return 0;
2270  return pat->pat_not ^ (e->env->newsgroups && patmatch(pat, e->env->newsgroups));
2271 #endif
2272  }
2273  mutt_error(_("error: unknown op %d (report this error)"), pat->op);
2274  return -1;
2275 }
Pattern matches date received.
Definition: pattern.h:115
static int match_user(int alladdr, struct AddressList *al1, struct AddressList *al2)
Matches the user&#39;s email Address.
Definition: pattern.c:1796
Deleted messages.
Definition: mutt.h:105
Pattern matches email&#39;s header.
Definition: pattern.h:122
Pattern matches MIME type.
Definition: pattern.h:144
Pattern matches &#39;Date:&#39; field.
Definition: pattern.h:114
static int match_threadcomplete(struct PatternHead *pat, PatternExecFlags 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:1832
static bool match_reference(struct Pattern *pat, struct ListHead *refs)
Match references against a Pattern.
Definition: pattern.c:1720
Pattern matches newsgroup.
Definition: pattern.h:146
Pattern matches email&#39;s score.
Definition: pattern.h:127
int pers_recip_all
^~p
Definition: pattern.h:89
struct MuttThread * thread
Thread of Emails.
Definition: email.h:94
static int match_addrlist(struct Pattern *pat, bool match_personal, int n,...)
Match a Pattern against and Address list.
Definition: pattern.c:1690
Message is part of a broken thread.
Definition: pattern.h:118
Pattern matches email&#39;s size.
Definition: pattern.h:128
struct Body * content
List of MIME parts.
Definition: email.h:90
int mutt_is_list_recipient(bool alladdr, struct Envelope *e)
Matches known mailing lists.
Definition: pattern.c:1783
Flagged messages.
Definition: mutt.h:106
Pattern matches &#39;From:&#39; field.
Definition: pattern.h:113
#define MUTT_MAXRANGE
Definition: pattern.c:99
Email is from the user.
Definition: pattern.h:134
#define _(a)
Definition: message.h:28
Email is on mailing list.
Definition: pattern.h:131
struct TagHead tags
For drivers that support server tagging.
Definition: email.h:106
Pattern matches a child email.
Definition: pattern.h:108
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:121
bool expired
Already expired?
Definition: email.h:52
Pattern matches email&#39;s Message-Id.
Definition: pattern.h:119
Messages that have been replied to.
Definition: mutt.h:99
int sub_all
^~u
Definition: pattern.h:87
Pattern matches message number.
Definition: pattern.h:126
Email is on subscribed mailing list.
Definition: pattern.h:132
static int is_pattern_cache_set(int cache_entry)
Is a given Pattern cached?
Definition: pattern.c:1985
All messages.
Definition: mutt.h:95
bool tagged
Email is tagged.
Definition: email.h:44
char * driver_tags_get(struct TagHead *head)
Get tags.
Definition: tags.c:143
bool read
Email is read.
Definition: email.h:51
bool dynamic
evaluate date ranges at run time
Definition: pattern.h:56
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:68
char * message_id
Message ID.
Definition: envelope.h:55
static int match_threadparent(struct PatternHead *pat, PatternExecFlags flags, struct Mailbox *m, struct MuttThread *t)
Match Pattern against an email&#39;s parent.
Definition: pattern.c:1870
bool old
Email is seen, but unread.
Definition: email.h:50
#define SEC_GOODSIGN
Email has a valid signature.
Definition: ncrypt.h:123
struct AddressList from
Email&#39;s &#39;From&#39; list.
Definition: envelope.h:43
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:117
Duplicate message.
Definition: pattern.h:116
struct Envelope * env
Envelope information.
Definition: email.h:89
struct AddressList cc
Email&#39;s &#39;Cc&#39; list.
Definition: envelope.h:45
bool pat_not
Definition: pattern.h:50
bool superseded
Got superseded?
Definition: email.h:53
int mutt_is_subscribed_list_recipient(bool alladdr, struct Envelope *e)
Matches subscribed mailing lists.
Definition: pattern.c:1771
int min
Definition: pattern.h:58
static bool perform_and(struct PatternHead *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Perform a logical AND on a set of Patterns.
Definition: pattern.c:1646
int score
Message score.
Definition: email.h:88
time_t date_sent
Time when the message was sent (UTC)
Definition: email.h:81
Old messages.
Definition: mutt.h:98
int pers_from_one
~P
Definition: pattern.h:92
struct MuttThread * child
Child of this Thread.
Definition: thread.h:46
bool duplicate_thread
Duplicated Email in Thread.
Definition: thread.h:37
Server-side pattern matches.
Definition: pattern.h:141
Pattern matches &#39;Cc:&#39; field.
Definition: pattern.h:110
#define SEC_SIGN
Email is signed.
Definition: ncrypt.h:122
int pers_recip_one
~p
Definition: pattern.h:90
Message is unreferenced in the thread.
Definition: pattern.h:117
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
bool fake_thread
Emails grouped by Subject.
Definition: thread.h:36
Pattern matches keyword/label.
Definition: pattern.h:140
Either pattern can match.
Definition: pattern.h:105
size_t num_hidden
Number of hidden messages in this view.
Definition: email.h:75
#define PGP_KEY
Definition: ncrypt.h:139
Pattern matches email&#39;s spam score.
Definition: pattern.h:123
Superseded messages.
Definition: mutt.h:111
Tagged messages.
Definition: mutt.h:107
Message is encrypted.
Definition: pattern.h:138
char * data
Pointer to data.
Definition: buffer.h:35
Pattern matches &#39;Subject:&#39; field.
Definition: pattern.h:112
int list_all
^~l
Definition: pattern.h:85
New messages.
Definition: mutt.h:97
Messages that have been read.
Definition: mutt.h:100
static int get_pattern_cache_value(int cache_entry)
Get pattern cache value.
Definition: pattern.c:1975
Email is addressed to the user.
Definition: pattern.h:133
Message has PGP key.
Definition: pattern.h:139
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:73
short op
Definition: pattern.h:49
Pattern matches parent.
Definition: pattern.h:107
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:73
static int perform_or(struct PatternHead *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Perform a logical OR on a set of Patterns.
Definition: pattern.c:1668
Expired messages.
Definition: mutt.h:110
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:130
int pers_from_all
^~P
Definition: pattern.h:91
Unread messages.
Definition: mutt.h:101
struct Buffer * spam
Spam header.
Definition: envelope.h:66
Pattern matches email&#39;s body.
Definition: pattern.h:121
static bool msg_search(struct Mailbox *m, struct Pattern *pat, int msgno)
Search an email.
Definition: pattern.c:1086
char * subject
Email&#39;s subject.
Definition: envelope.h:52
bool flagged
Marked important?
Definition: email.h:43
struct PatternHead * child
arguments to logical op
Definition: pattern.h:61
char * newsgroups
List of newsgroups.
Definition: envelope.h:61
#define EMSG(e)
Definition: pattern.c:95
Message is signed.
Definition: pattern.h:136
bool deleted
Email is deleted.
Definition: email.h:45
#define mutt_error(...)
Definition: logging.h:84
bool replied
Email has been replied to.
Definition: email.h:54
Thread is collapsed.
Definition: pattern.h:111
Pattern matches sender.
Definition: pattern.h:125
Both patterns must match.
Definition: pattern.h:104
#define FREE(x)
Definition: memory.h:40
Message is crypographically verified.
Definition: pattern.h:137
int max
Definition: pattern.h:59
Pattern matches &#39;References:&#39; or &#39;In-Reply-To:&#39; field.
Definition: pattern.h:129
static bool match_update_dynamic_date(struct Pattern *pat)
Update a dynamic date pattern.
Definition: pattern.c:1932
bool stringmatch
Definition: pattern.h:52
Pattern matches message tags.
Definition: pattern.h:142
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:44
struct AddressList sender
Email&#39;s sender.
Definition: envelope.h:47
Pattern matches any address field.
Definition: pattern.h:135
User is a recipient of the email.
Definition: pattern.h:130
bool alladdr
Definition: pattern.h:51
static bool 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:1950
static int match_threadchildren(struct PatternHead *pat, PatternExecFlags flags, struct Mailbox *m, struct MuttThread *t)
Match Pattern against an email&#39;s children.
Definition: pattern.c:1889
Pattern matches email thread.
Definition: pattern.h:106
int mutt_count_body_parts(struct Mailbox *m, struct Email *e)
Count the MIME Body parts.
Definition: mutt_parse.c:216
Pattern matches &#39;To:&#39; field.
Definition: pattern.h:109
static void set_pattern_cache_value(int *cache_entry, int value)
Sets a value in the PatternCache cache entry.
Definition: pattern.c:1964
Pattern matches raw email text.
Definition: pattern.h:124
struct ListHead references
message references (in reverse order)
Definition: envelope.h:67
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
char * x_label
X-Label.
Definition: envelope.h:58
#define WithCrypto
Definition: ncrypt.h:156
Pattern matches number of attachments.
Definition: pattern.h:143
int list_one
~l
Definition: pattern.h:86
time_t received
Time when the message was placed in the mailbox.
Definition: email.h:82
Message-Id is among results from an external query.
Definition: pattern.h:120
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:1066
bool matched
Search matches this Email.
Definition: email.h:68
int msgno
Number displayed to the user.
Definition: email.h:86
int sub_one
~u
Definition: pattern.h:88
static void quote_simple ( const char *  str,
struct Buffer buf 
)
static

Apply simple quoting to a string.

Parameters
strString to quote
bufBuffer for the result

Definition at line 2282 of file pattern.c.

2283 {
2284  mutt_buffer_reset(buf);
2285  mutt_buffer_addch(buf, '"');
2286  while (*str)
2287  {
2288  if ((*str == '\\') || (*str == '"'))
2289  mutt_buffer_addch(buf, '\\');
2290  mutt_buffer_addch(buf, *str++);
2291  }
2292  mutt_buffer_addch(buf, '"');
2293 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:76
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:271
void mutt_check_simple ( struct Buffer buf,
const char *  simple 
)

Convert a simple search into a real request.

Parameters
bufBuffer for the result
simpleSearch string to convert

Definition at line 2300 of file pattern.c.

2301 {
2302  bool do_simple = true;
2303 
2304  for (const char *p = mutt_b2s(buf); p && (p[0] != '\0'); p++)
2305  {
2306  if ((p[0] == '\\') && (p[1] != '\0'))
2307  p++;
2308  else if ((p[0] == '~') || (p[0] == '=') || (p[0] == '%'))
2309  {
2310  do_simple = false;
2311  break;
2312  }
2313  }
2314 
2315  /* XXX - is mutt_str_strcasecmp() right here, or should we use locale's
2316  * equivalences? */
2317 
2318  if (do_simple) /* yup, so spoof a real request */
2319  {
2320  /* convert old tokens into the new format */
2321  if ((mutt_str_strcasecmp("all", mutt_b2s(buf)) == 0) ||
2322  (mutt_str_strcmp("^", mutt_b2s(buf)) == 0) ||
2323  (mutt_str_strcmp(".", mutt_b2s(buf)) == 0)) /* ~A is more efficient */
2324  {
2325  mutt_buffer_strcpy(buf, "~A");
2326  }
2327  else if (mutt_str_strcasecmp("del", mutt_b2s(buf)) == 0)
2328  mutt_buffer_strcpy(buf, "~D");
2329  else if (mutt_str_strcasecmp("flag", mutt_b2s(buf)) == 0)
2330  mutt_buffer_strcpy(buf, "~F");
2331  else if (mutt_str_strcasecmp("new", mutt_b2s(buf)) == 0)
2332  mutt_buffer_strcpy(buf, "~N");
2333  else if (mutt_str_strcasecmp("old", mutt_b2s(buf)) == 0)
2334  mutt_buffer_strcpy(buf, "~O");
2335  else if (mutt_str_strcasecmp("repl", mutt_b2s(buf)) == 0)
2336  mutt_buffer_strcpy(buf, "~Q");
2337  else if (mutt_str_strcasecmp("read", mutt_b2s(buf)) == 0)
2338  mutt_buffer_strcpy(buf, "~R");
2339  else if (mutt_str_strcasecmp("tag", mutt_b2s(buf)) == 0)
2340  mutt_buffer_strcpy(buf, "~T");
2341  else if (mutt_str_strcasecmp("unread", mutt_b2s(buf)) == 0)
2342  mutt_buffer_strcpy(buf, "~U");
2343  else
2344  {
2345  struct Buffer *tmp = mutt_buffer_pool_get();
2346  quote_simple(mutt_b2s(buf), tmp);
2347  mutt_file_expand_fmt(buf, simple, mutt_b2s(tmp));
2349  }
2350  }
2351 }
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
static void quote_simple(const char *str, struct Buffer *buf)
Apply simple quoting to a string.
Definition: pattern.c:2282
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
String manipulation buffer.
Definition: buffer.h:33
#define mutt_b2s(buf)
Definition: buffer.h:42
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
void mutt_file_expand_fmt(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1433
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
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 2359 of file pattern.c.

2360 {
2361  if (!e)
2362  return NULL;
2363 
2364  struct MuttThread *t = e->thread;
2365 
2366  while (t && t->parent)
2367  t = t->parent;
2368 
2369  return t;
2370 }
struct MuttThread * thread
Thread of Emails.
Definition: email.h:94
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
An Email conversation.
Definition: thread.h:34
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 2378 of file pattern.c.

2379 {
2380  if (!e)
2381  return false;
2382 
2383  struct MuttThread *me = top_of_thread(e);
2384  if (!me)
2385  return false;
2386 
2387  Context->mailbox->vcount = 0;
2388  Context->vsize = 0;
2389  Context->collapsed = false;
2390 
2391  for (int i = 0; i < Context->mailbox->msg_count; i++)
2392  {
2393  Context->mailbox->emails[i]->vnum = -1;
2394  Context->mailbox->emails[i]->limited = false;
2395  Context->mailbox->emails[i]->collapsed = false;
2396  Context->mailbox->emails[i]->num_hidden = 0;
2397 
2398  if (top_of_thread(Context->mailbox->emails[i]) == me)
2399  {
2400  struct Body *body = Context->mailbox->emails[i]->content;
2401 
2403  Context->mailbox->emails[i]->limited = true;
2405  Context->mailbox->vcount++;
2406  Context->vsize += (body->length + body->offset - body->hdr_offset);
2407  }
2408  }
2409  return true;
2410 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
The "current" mailbox.
Definition: context.h:39
int msg_count
Total number of messages.
Definition: mailbox.h:103
struct Body * content
List of MIME parts.
Definition: email.h:90
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
int vcount
The number of virtual messages.
Definition: mailbox.h:114
The body of an email.
Definition: body.h:34
struct Mailbox * mailbox
Definition: context.h:53
bool limited
Is this message in a limited view?
Definition: email.h:74
off_t vsize
Definition: context.h:41
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
static struct MuttThread * top_of_thread(struct Email *e)
Find the first email in the current thread.
Definition: pattern.c:2359
size_t num_hidden
Number of hidden messages in this view.
Definition: email.h:75
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:73
int vnum
Virtual message number.
Definition: email.h:87
An Email conversation.
Definition: thread.h:34
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:113
bool collapsed
are all threads collapsed?
Definition: context.h:51
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
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 2419 of file pattern.c.

2420 {
2421  struct Buffer err;
2422  int rc = -1;
2423  struct Progress progress;
2424  struct Buffer *buf = mutt_buffer_pool_get();
2425 
2427  if (prompt || (op != MUTT_LIMIT))
2428  {
2429  if ((mutt_get_field(prompt, buf->data, buf->dsize, MUTT_PATTERN | MUTT_CLEAR) != 0) ||
2430  !(mutt_b2s(buf)[0]))
2431  {
2433  return -1;
2434  }
2435  }
2436  mutt_buffer_fix_dptr(buf);
2437 
2438  mutt_message(_("Compiling search pattern..."));
2439 
2440  char *simple = mutt_str_strdup(mutt_b2s(buf));
2442 
2443  mutt_buffer_init(&err);
2444  err.dsize = 256;
2445  err.data = mutt_mem_malloc(err.dsize);
2446  struct PatternHead *pat = mutt_pattern_comp(buf->data, MUTT_FULL_MSG, &err);
2447  if (!pat)
2448  {
2449  mutt_error("%s", err.data);
2450  goto bail;
2451  }
2452 
2453 #ifdef USE_IMAP
2454  if ((Context->mailbox->magic == MUTT_IMAP) && (imap_search(Context->mailbox, pat) < 0))
2455  goto bail;
2456 #endif
2457 
2458  mutt_progress_init(&progress, _("Executing command on matching messages..."),
2460  (op == MUTT_LIMIT) ? Context->mailbox->msg_count :
2461  Context->mailbox->vcount);
2462 
2463  if (op == MUTT_LIMIT)
2464  {
2465  Context->mailbox->vcount = 0;
2466  Context->vsize = 0;
2467  Context->collapsed = false;
2468  int padding = mx_msg_padding_size(Context->mailbox);
2469 
2470  for (int i = 0; i < Context->mailbox->msg_count; i++)
2471  {
2472  mutt_progress_update(&progress, i, -1);
2473  /* new limit pattern implicitly uncollapses all threads */
2474  Context->mailbox->emails[i]->vnum = -1;
2475  Context->mailbox->emails[i]->limited = false;
2476  Context->mailbox->emails[i]->collapsed = false;
2477  Context->mailbox->emails[i]->num_hidden = 0;
2479  Context->mailbox, Context->mailbox->emails[i], NULL))
2480  {
2482  Context->mailbox->emails[i]->limited = true;
2484  Context->mailbox->vcount++;
2485  struct Body *b = Context->mailbox->emails[i]->content;
2486  Context->vsize += b->length + b->offset - b->hdr_offset + padding;
2487  }
2488  }
2489  }
2490  else
2491  {
2492  for (int i = 0; i < Context->mailbox->vcount; i++)
2493  {
2494  mutt_progress_update(&progress, i, -1);
2496  Context->mailbox->emails[Context->mailbox->v2r[i]], NULL))
2497  {
2498  switch (op)
2499  {
2500  case MUTT_UNDELETE:
2503  MUTT_PURGE, false);
2504  /* fallthrough */
2505  case MUTT_DELETE:
2508  MUTT_DELETE, (op == MUTT_DELETE));
2509  break;
2510  case MUTT_TAG:
2511  case MUTT_UNTAG:
2514  MUTT_TAG, (op == MUTT_TAG));
2515  break;
2516  }
2517  }
2518  }
2519  }
2520 
2521  mutt_clear_error();
2522 
2523  if (op == MUTT_LIMIT)
2524  {
2525  /* drop previous limit pattern */
2526  FREE(&Context->pattern);
2528 
2530  mutt_error(_("No messages matched criteria"));
2531 
2532  /* record new limit pattern, unless match all */
2533  const char *pbuf = buf->data;
2534  while (*pbuf == ' ')
2535  pbuf++;
2536  if (mutt_str_strcmp(pbuf, "~A") != 0)
2537  {
2538  Context->pattern = simple;
2539  simple = NULL; /* don't clobber it */
2541  }
2542  }
2543 
2544  rc = 0;
2545 
2546 bail:
2548  FREE(&simple);
2549  mutt_pattern_free(&pat);
2550  FREE(&err.data);
2551 
2552  return rc;
2553 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
The "current" mailbox.
Definition: context.h:39
#define MUTT_PROGRESS_MSG
message-based progress
Definition: progress.h:33
#define NONULL(x)
Definition: string2.h:37
int msg_count
Total number of messages.
Definition: mailbox.h:103
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:68
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:68
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
#define mutt_message(...)
Definition: logging.h:83
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:2300
Messages in limited view.
Definition: mutt.h:109
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
struct Body * content
List of MIME parts.
Definition: email.h:90
#define MUTT_FULL_MSG
enable body and header matching
Definition: pattern.h:41
struct PatternHead * mutt_pattern_comp(const char *s, int flags, struct Buffer *err)
Create a Pattern.
Definition: pattern.c:1389
void mutt_progress_update(struct Progress *progress, long pos, int percent)
Update the state of the progress bar.
Definition: progress.c:171
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:114
String manipulation buffer.
Definition: buffer.h:33
Messages to be un-deleted.
Definition: mutt.h:103
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
int imap_search(struct Mailbox *m, const struct PatternHead *pat)
Find a matching mailbox.
Definition: imap.c:1351
#define _(a)
Definition: message.h:28
Messages to be purged (bypass trash)
Definition: mutt.h:104
A progress bar.
Definition: progress.h:38
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:70
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
int vcount
The number of virtual messages.
Definition: mailbox.h:114
The body of an email.
Definition: body.h:34
struct PatternHead * limit_pattern
compiled limit pattern
Definition: context.h:43
size_t dsize
Length of data.
Definition: buffer.h:37
struct Mailbox * mailbox
Definition: context.h:53
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:117
bool limited
Is this message in a limited view?
Definition: email.h:74
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:212
off_t vsize
Definition: context.h:41
#define mutt_b2s(buf)
Definition: buffer.h:42
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2005
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
#define SLIST_FIRST(head)
Definition: queue.h:229
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
Messages to be deleted.
Definition: mutt.h:102
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
size_t num_hidden
Number of hidden messages in this view.
Definition: email.h:75
Tagged messages.
Definition: mutt.h:107
char * data
Pointer to data.
Definition: buffer.h:35
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:73
int vnum
Virtual message number.
Definition: email.h:87
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:73
WHERE char * C_SimpleSearch
Config: Pattern to search for when search doesn&#39;t contain ~&#39;s.
Definition: globals.h:138
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:113
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
bool collapsed
are all threads collapsed?
Definition: context.h:51
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
Messages to be un-tagged.
Definition: mutt.h:108
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size.
Definition: mx.c:1467
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:61
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
char * pattern
limit pattern string
Definition: context.h:42
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:615
WHERE short C_ReadInc
Config: Update the progress bar after this many records read (0 to disable)
Definition: globals.h:148
void mutt_pattern_free(struct PatternHead **pat)
Free a Pattern.
Definition: pattern.c:1337
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 2562 of file pattern.c.

2563 {
2564  struct Progress progress;
2565 
2566  if (!*LastSearch || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
2567  {
2568  char buf[256];
2569  mutt_str_strfcpy(buf, (LastSearch[0] != '\0') ? LastSearch : "", sizeof(buf));
2570  if ((mutt_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
2571  _("Search for: ") :
2572  _("Reverse search for: "),
2573  buf, sizeof(buf), MUTT_CLEAR | MUTT_PATTERN) != 0) ||
2574  !buf[0])
2575  {
2576  return -1;
2577  }
2578 
2579  if ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT))
2580  OptSearchReverse = false;
2581  else
2582  OptSearchReverse = true;
2583 
2584  /* compare the *expanded* version of the search pattern in case
2585  * $simple_search has changed while we were searching */
2586  struct Buffer *tmp = mutt_buffer_pool_get();
2587  mutt_buffer_strcpy(tmp, buf);
2589 
2590  if (!SearchPattern || (mutt_str_strcmp(mutt_b2s(tmp), LastSearchExpn) != 0))
2591  {
2592  struct Buffer err;
2593  mutt_buffer_init(&err);
2594  OptSearchInvalid = true;
2595  mutt_str_strfcpy(LastSearch, buf, sizeof(LastSearch));
2597  mutt_message(_("Compiling search pattern..."));
2599  err.dsize = 256;
2600  err.data = mutt_mem_malloc(err.dsize);
2602  if (!SearchPattern)
2603  {
2605  mutt_error("%s", err.data);
2606  FREE(&err.data);
2607  LastSearch[0] = '\0';
2608  LastSearchExpn[0] = '\0';
2609  return -1;
2610  }
2611  FREE(&err.data);
2612  mutt_clear_error();
2613  }
2614 
2616  }
2617 
2618  if (OptSearchInvalid)
2619  {
2620  for (int i = 0; i < Context->mailbox->msg_count; i++)
2621  Context->mailbox->emails[i]->searched = false;
2622 #ifdef USE_IMAP
2623  if ((Context->mailbox->magic == MUTT_IMAP) &&
2625  return -1;
2626 #endif
2627  OptSearchInvalid = false;
2628  }
2629 
2630  int incr = OptSearchReverse ? -1 : 1;
2631  if (op == OP_SEARCH_OPPOSITE)
2632  incr = -incr;
2633 
2634  mutt_progress_init(&progress, _("Searching..."), MUTT_PROGRESS_MSG, C_ReadInc,
2635  Context->mailbox->vcount);
2636 
2637  for (int i = cur + incr, j = 0; j != Context->mailbox->vcount; j++)
2638  {
2639  const char *msg = NULL;
2640  mutt_progress_update(&progress, j, -1);
2641  if (i > Context->mailbox->vcount - 1)
2642  {
2643  i = 0;
2644  if (C_WrapSearch)
2645  msg = _("Search wrapped to top");
2646  else
2647  {
2648  mutt_message(_("Search hit bottom without finding match"));
2649  return -1;
2650  }
2651  }
2652  else if (i < 0)
2653  {
2654  i = Context->mailbox->vcount - 1;
2655  if (C_WrapSearch)
2656  msg = _("Search wrapped to bottom");
2657  else
2658  {
2659  mutt_message(_("Search hit top without finding match"));
2660  return -1;
2661  }
2662  }
2663 
2664  struct Email *e = Context->mailbox->emails[Context->mailbox->v2r[i]];
2665  if (e->searched)
2666  {
2667  /* if we've already evaluated this message, use the cached value */
2668  if (e->matched)
2669  {
2670  mutt_clear_error();
2671  if (msg && *msg)
2672  mutt_message(msg);
2673  return i;
2674  }
2675  }
2676  else
2677  {
2678  /* remember that we've already searched this message */
2679  e->searched = true;
2681  Context->mailbox, e, NULL);
2682  if (e->matched > 0)
2683  {
2684  mutt_clear_error();
2685  if (msg && *msg)
2686  mutt_message(msg);
2687  return i;
2688  }
2689  }
2690 
2691  if (SigInt)
2692  {
2693  mutt_error(_("Search interrupted"));
2694  SigInt = 0;
2695  return -1;
2696  }
2697 
2698  i += incr;
2699  }
2700 
2701  mutt_error(_("Not found"));
2702  return -1;
2703 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:111
The "current" mailbox.
Definition: context.h:39
#define MUTT_PROGRESS_MSG
message-based progress
Definition: progress.h:33
#define NONULL(x)
Definition: string2.h:37
int msg_count
Total number of messages.
Definition: mailbox.h:103
The envelope/body of an email.
Definition: email.h:37
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:68
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:75
#define mutt_message(...)
Definition: logging.h:83
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:2300
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:83
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:86
#define MUTT_FULL_MSG
enable body and header matching
Definition: pattern.h:41
struct PatternHead * mutt_pattern_comp(const char *s, int flags, struct Buffer *err)
Create a Pattern.
Definition: pattern.c:1389
void mutt_progress_update(struct Progress *progress, long pos, int percent)
Update the state of the progress bar.
Definition: progress.c:171
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:114
String manipulation buffer.
Definition: buffer.h:33
int imap_search(struct Mailbox *m, const struct PatternHead *pat)
Find a matching mailbox.
Definition: imap.c:1351
#define _(a)
Definition: message.h:28
static char LastSearch[256]
last pattern searched for
Definition: pattern.c:202
WHERE bool C_WrapSearch
Config: Wrap around when the search hits the end.
Definition: globals.h:259
bool searched
Email has been searched.
Definition: email.h:67
A progress bar.
Definition: progress.h:38
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:70
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
int vcount
The number of virtual messages.
Definition: mailbox.h:114
struct Mailbox * mailbox
Definition: context.h:53
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:117
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
#define mutt_b2s(buf)
Definition: buffer.h:42
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:2005
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:314
static char LastSearchExpn[1024]
expanded version of LastSearch
Definition: pattern.c:203
#define SLIST_FIRST(head)
Definition: queue.h:229
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
char * data
Pointer to data.
Definition: buffer.h:35
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:750
WHERE bool OptSearchInvalid
(pseudo) used to invalidate the search pat
Definition: options.h:49
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:73
WHERE char * C_SimpleSearch
Config: Pattern to search for when search doesn&#39;t contain ~&#39;s.
Definition: globals.h:138
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:113
static struct PatternHead * SearchPattern
current search pattern
Definition: pattern.c:201
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:61
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:53
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
WHERE bool OptSearchReverse
(pseudo) used by ci_search_command
Definition: options.h:50
WHERE short C_ReadInc
Config: Update the progress bar after this many records read (0 to disable)
Definition: globals.h:148
bool matched
Search matches this Email.
Definition: email.h:68
void mutt_pattern_free(struct PatternHead **pat)
Free a Pattern.
Definition: pattern.c:1337

Variable Documentation

bool C_ThoroughSearch

Config: Decode headers and messages before searching them.

Definition at line 73 of file pattern.c.

struct RangeRegex range_regexes[]
static
Initial value:
= {
[RANGE_K_REL] = { RANGE_REL_RX, 1, 3, 0, { 0 } },
[RANGE_K_ABS] = { RANGE_ABS_RX, 1, 3, 0, { 0 } },
[RANGE_K_LT] = { RANGE_LT_RX, 1, 2, 0, { 0 } },
[RANGE_K_GT] = { RANGE_GT_RX, 2, 1, 0, { 0 } },
[RANGE_K_BARE] = { RANGE_BARE_RX, 1, 1, 0, { 0 } },
}
Single symbol.
Definition: pattern.c:150
#define RANGE_REL_RX
Definition: pattern.c:79
#define RANGE_ABS_RX
Definition: pattern.c:83
Greater-than range.
Definition: pattern.c:149
#define RANGE_LT_RX
Definition: pattern.c:86
#define RANGE_BARE_RX
Definition: pattern.c:90
Absolute range.
Definition: pattern.c:147
#define RANGE_GT_RX
Definition: pattern.c:87
Less-than range.
Definition: pattern.c:148
Relative range.
Definition: pattern.c:146

Set of Regexes for various range types.

This array, will also contain the compiled regexes.

Definition at line 192 of file pattern.c.

struct PatternHead* SearchPattern = NULL
static

current search pattern

Definition at line 201 of file pattern.c.

char LastSearch[256] = { 0 }
static

last pattern searched for

Definition at line 202 of file pattern.c.

char LastSearchExpn[1024] = { 0 }
static

expanded version of LastSearch

Definition at line 203 of file pattern.c.

const struct PatternFlags Flags[]
static

Lookup table for all patterns.

Definition at line 1241 of file pattern.c.