NeoMutt  2018-07-16 +2388-bcedc8
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 "email/lib.h"
#include "core/lib.h"
#include "mutt.h"
#include "pattern.h"
#include "alias.h"
#include "context.h"
#include "copy.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 "mx.h"
#include "ncrypt/ncrypt.h"
#include "opcodes.h"
#include "options.h"
#include "progress.h"
#include "protos.h"
#include "state.h"
#include "imap/imap.h"
+ Include dependency graph for pattern.c:

Go to the source code of this file.

Data Structures

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

Macros

#define RANGE_NUM_RX   "([[:digit:]]+|0x[[:xdigit:]]+)[MmKk]?"
 
#define RANGE_REL_SLOT_RX   "[[:blank:]]*([.^$]|-?" RANGE_NUM_RX ")?[[:blank:]]*"
 
#define RANGE_REL_RX   "^" RANGE_REL_SLOT_RX "," RANGE_REL_SLOT_RX
 
#define RANGE_ABS_SLOT_RX   "[[:blank:]]*([.^$]|" RANGE_NUM_RX ")?[[:blank:]]*"
 
#define RANGE_ABS_RX   "^" RANGE_ABS_SLOT_RX "-" RANGE_ABS_SLOT_RX
 
#define RANGE_LT_RX   "^()[[:blank:]]*(<[[:blank:]]*" RANGE_NUM_RX ")[[:blank:]]*"
 
#define RANGE_GT_RX   "^()[[:blank:]]*(>[[:blank:]]*" RANGE_NUM_RX ")[[:blank:]]*"
 
#define RANGE_BARE_RX   "^[[:blank:]]*([.^$]|" RANGE_NUM_RX ")[[:blank:]]*"
 
#define RANGE_RX_GROUPS   5
 
#define KILO   1024
 
#define MEGA   1048576
 
#define 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, PatternCompFlags 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 74 of file pattern.c.

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

Definition at line 75 of file pattern.c.

#define RANGE_REL_RX   "^" RANGE_REL_SLOT_RX "," RANGE_REL_SLOT_RX

Definition at line 76 of file pattern.c.

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

Definition at line 79 of file pattern.c.

#define RANGE_ABS_RX   "^" RANGE_ABS_SLOT_RX "-" RANGE_ABS_SLOT_RX

Definition at line 80 of file pattern.c.

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

Definition at line 83 of file pattern.c.

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

Definition at line 84 of file pattern.c.

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

Definition at line 87 of file pattern.c.

#define RANGE_RX_GROUPS   5

Definition at line 88 of file pattern.c.

#define KILO   1024

Definition at line 90 of file pattern.c.

#define MEGA   1048576

Definition at line 91 of file pattern.c.

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

Definition at line 92 of file pattern.c.

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

Definition at line 93 of file pattern.c.

#define MUTT_MAXRANGE   -1

Definition at line 96 of file pattern.c.

#define MUTT_PDR_NO_FLAGS   0

No flags are set.

Definition at line 99 of file pattern.c.

#define MUTT_PDR_MINUS   (1 << 0)

Pattern contains a range.

Definition at line 100 of file pattern.c.

#define MUTT_PDR_PLUS   (1 << 1)

Extend the range using '+'.

Definition at line 101 of file pattern.c.

#define MUTT_PDR_WINDOW   (1 << 2)

Extend the range in both directions using '*'.

Definition at line 102 of file pattern.c.

#define MUTT_PDR_ABSOLUTE   (1 << 3)

Absolute pattern range.

Definition at line 103 of file pattern.c.

#define MUTT_PDR_DONE   (1 << 4)

Pattern parse successfully.

Definition at line 104 of file pattern.c.

#define MUTT_PDR_ERROR   (1 << 8)

Invalid pattern.

Definition at line 105 of file pattern.c.

#define MUTT_PDR_ERRORDONE   (MUTT_PDR_ERROR | MUTT_PDR_DONE)

Definition at line 107 of file pattern.c.

#define RANGE_DOT   '.'

Definition at line 109 of file pattern.c.

#define RANGE_CIRCUM   '^'

Definition at line 110 of file pattern.c.

#define RANGE_DOLLAR   '$'

Definition at line 111 of file pattern.c.

#define RANGE_LT   '<'

Definition at line 112 of file pattern.c.

#define RANGE_GT   '>'

Definition at line 113 of file pattern.c.

Typedef Documentation

typedef uint16_t ParseDateRangeFlags

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

Definition at line 98 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_PC_PATTERN_DYNAMIC
sString to parse
errBuffer for error messages
Return values
trueIf the pattern was read successfully

Definition at line 169 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 1733 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 119 of file pattern.c.

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

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

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

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

206 {
207  struct Buffer buf;
208 
209  mutt_buffer_init(&buf);
210  char *pexpr = s->dptr;
211  if ((mutt_extract_token(&buf, s, MUTT_TOKEN_PATTERN | MUTT_TOKEN_COMMENT) != 0) || !buf.data)
212  {
213  mutt_buffer_printf(err, _("Error in expression: %s"), pexpr);
214  FREE(&buf.data);
215  return false;
216  }
217  if (buf.data[0] == '\0')
218  {
219  mutt_buffer_printf(err, "%s", _("Empty expression"));
220  FREE(&buf.data);
221  return false;
222  }
223 
224  if (pat->stringmatch)
225  {
226  pat->p.str = mutt_str_strdup(buf.data);
227  pat->ign_case = mutt_mb_is_lower(buf.data);
228  FREE(&buf.data);
229  }
230  else if (pat->groupmatch)
231  {
232  pat->p.group = mutt_pattern_group(buf.data);
233  FREE(&buf.data);
234  }
235  else
236  {
237  pat->p.regex = mutt_mem_malloc(sizeof(regex_t));
238  int case_flags = mutt_mb_is_lower(buf.data) ? REG_ICASE : 0;
239  int rc = REG_COMP(pat->p.regex, buf.data, REG_NEWLINE | REG_NOSUB | case_flags);
240  if (rc != 0)
241  {
242  char errmsg[256];
243  regerror(rc, pat->p.regex, errmsg, sizeof(errmsg));
244  mutt_buffer_add_printf(err, "'%s': %s", buf.data, errmsg);
245  FREE(&buf.data);
246  FREE(&pat->p.regex);
247  return false;
248  }
249  FREE(&buf.data);
250  }
251 
252  return true;
253 }
regex_t * regex
Definition: pattern.h:65
#define MUTT_TOKEN_COMMENT
Don&#39;t reap comments.
Definition: mutt.h:83
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:56
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:2638
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:67
struct Group * group
Definition: pattern.h:66
#define FREE(x)
Definition: memory.h:40
bool groupmatch
Definition: pattern.h:55
bool stringmatch
Definition: pattern.h:54
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:82
struct Group * mutt_pattern_group(const char *pat)
Match a pattern to a Group.
Definition: group.c:66

+ Here is the call graph for this function:

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

260 {
261  struct ListHead *msgid_list = (struct ListHead *) (user_data);
262  char *nows = mutt_str_skip_whitespace(line);
263  if (!*nows)
264  return true;
266  mutt_list_insert_tail(msgid_list, mutt_str_strdup(nows));
267  return true;
268 }
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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

274 {
275  struct Buffer cmd_buf;
276  struct Buffer tok_buf;
277  FILE *fp = NULL;
278 
280  {
281  mutt_buffer_printf(err, "%s", _("No search command defined"));
282  return false;
283  }
284 
285  mutt_buffer_init(&tok_buf);
286  char *pexpr = s->dptr;
287  if ((mutt_extract_token(&tok_buf, s, MUTT_TOKEN_PATTERN | MUTT_TOKEN_COMMENT) != 0) ||
288  !tok_buf.data)
289  {
290  mutt_buffer_printf(err, _("Error in expression: %s"), pexpr);
291  return false;
292  }
293  if (*tok_buf.data == '\0')
294  {
295  mutt_buffer_printf(err, "%s", _("Empty expression"));
296  FREE(&tok_buf.data);
297  return false;
298  }
299 
300  mutt_buffer_init(&cmd_buf);
302  mutt_buffer_addch(&cmd_buf, ' ');
303  if (!Context || !Context->mailbox)
304  {
305  mutt_buffer_addch(&cmd_buf, '/');
306  }
307  else
308  {
309  char *escaped_folder = mutt_path_escape(mutt_b2s(Context->mailbox->pathbuf));
310  mutt_debug(LL_DEBUG2, "escaped folder path: %s\n", escaped_folder);
311  mutt_buffer_addch(&cmd_buf, '\'');
312  mutt_buffer_addstr(&cmd_buf, escaped_folder);
313  mutt_buffer_addch(&cmd_buf, '\'');
314  }
315  mutt_buffer_addch(&cmd_buf, ' ');
316  mutt_buffer_addstr(&cmd_buf, tok_buf.data);
317  FREE(&tok_buf.data);
318 
319  mutt_message(_("Running search command: %s ..."), cmd_buf.data);
320  pat->ismulti = true;
322  pid_t pid = mutt_create_filter(cmd_buf.data, NULL, &fp, NULL);
323  if (pid < 0)
324  {
325  mutt_buffer_printf(err, "unable to fork command: %s\n", cmd_buf.data);
326  FREE(&cmd_buf.data);
327  return false;
328  }
329 
331  mutt_file_fclose(&fp);
332  mutt_wait_filter(pid);
333  FREE(&cmd_buf.data);
334  return true;
335 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:217
The "current" mailbox.
Definition: context.h:36
#define mutt_message(...)
Definition: logging.h:83
#define MUTT_TOKEN_COMMENT
Don&#39;t reap comments.
Definition: mutt.h:83
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:50
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:41
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:2638
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:259
struct Buffer * pathbuf
Definition: mailbox.h:94
union Pattern::@2 p
#define FREE(x)
Definition: memory.h:40
struct ListHead multi_cases
Definition: pattern.h:68
#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:114
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:228
#define MUTT_TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition: mutt.h:82
bool ismulti
multiple case (only for I pattern now)
Definition: pattern.h:59
char * mutt_path_escape(const char *src)
Escapes single quotes in a path for a command string.
Definition: path.c:558

+ Here is the call graph for this function:

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

Calculate a symbolic offset.

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

Definition at line 349 of file pattern.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

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

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

Examples:

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

Definition at line 402 of file pattern.c.

403 {
404  char *p = NULL;
405  struct tm tm = mutt_date_localtime(MUTT_DATE_NOW);
406 
407  t->tm_mday = strtol(s, &p, 10);
408  if ((t->tm_mday < 1) || (t->tm_mday > 31))
409  {
410  mutt_buffer_printf(err, _("Invalid day of month: %s"), s);
411  return NULL;
412  }
413  if (*p != '/')
414  {
415  /* fill in today's month and year */
416  t->tm_mon = tm.tm_mon;
417  t->tm_year = tm.tm_year;
418  return p;
419  }
420  p++;
421  t->tm_mon = strtol(p, &p, 10) - 1;
422  if ((t->tm_mon < 0) || (t->tm_mon > 11))
423  {
424  mutt_buffer_printf(err, _("Invalid month: %s"), p);
425  return NULL;
426  }
427  if (*p != '/')
428  {
429  t->tm_year = tm.tm_year;
430  return p;
431  }
432  p++;
433  t->tm_year = strtol(p, &p, 10);
434  if (t->tm_year < 70) /* year 2000+ */
435  t->tm_year += 100;
436  else if (t->tm_year > 1900)
437  t->tm_year -= 1900;
438  return p;
439 }
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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Parse a date range.

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

Definition at line 451 of file pattern.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Put a date range in the correct order.

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

Definition at line 537 of file pattern.c.

538 {
539  if ((min->tm_year > max->tm_year) ||
540  ((min->tm_year == max->tm_year) && (min->tm_mon > max->tm_mon)) ||
541  ((min->tm_year == max->tm_year) && (min->tm_mon == max->tm_mon) &&
542  (min->tm_mday > max->tm_mday)))
543  {
544  int tmp;
545 
546  tmp = min->tm_year;
547  min->tm_year = max->tm_year;
548  max->tm_year = tmp;
549 
550  tmp = min->tm_mon;
551  min->tm_mon = max->tm_mon;
552  max->tm_mon = tmp;
553 
554  tmp = min->tm_mday;
555  min->tm_mday = max->tm_mday;
556  max->tm_mday = tmp;
557 
558  min->tm_hour = 0;
559  min->tm_min = 0;
560  min->tm_sec = 0;
561  max->tm_hour = 23;
562  max->tm_min = 59;
563  max->tm_sec = 59;
564  }
565 }

+ Here is the caller graph for this function:

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

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

794 {
795  size_t ds = err->dsize;
796 
797  if (regerror(regerr, preg, err->data, ds) > ds)
798  mutt_debug(LL_DEBUG2, "warning: buffer too small for regerror\n");
799  /* The return value is fixed, exists only to shorten code at callsite */
800  return RANGE_E_SYNTAX;
801 }
Range contains syntax error.
Definition: pattern.c:122
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

+ Here is the caller graph for this function:

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

Do we need a Context for this Pattern?

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

Definition at line 812 of file pattern.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Parse a number range.

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

Definition at line 847 of file pattern.c.

848 {
849  int num = (int) strtol(&s->dptr[pmatch[group].rm_so], NULL, 0);
850  unsigned char c = (unsigned char) (s->dptr[pmatch[group].rm_eo - 1]);
851  if (toupper(c) == 'K')
852  num *= KILO;
853  else if (toupper(c) == 'M')
854  num *= MEGA;
855  switch (kind)
856  {
857  case RANGE_K_REL:
858  return num + CTX_MSGNO(Context);
859  case RANGE_K_LT:
860  return num - 1;
861  case RANGE_K_GT:
862  return num + 1;
863  default:
864  return num;
865  }
866 }
The "current" mailbox.
Definition: context.h:36
#define MEGA
Definition: pattern.c:91
#define KILO
Definition: pattern.c:90
Greater-than range.
Definition: pattern.c:146
char * dptr
Current read/write position.
Definition: buffer.h:36
#define CTX_MSGNO(ctx)
Definition: pattern.c:93
Less-than range.
Definition: pattern.c:145
Relative range.
Definition: pattern.c:143

+ Here is the caller graph for this function:

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

Parse a range of message numbers.

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

Definition at line 877 of file pattern.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void order_range ( struct Pattern pat)
static

Put a range in order.

Parameters
patPattern to check

Definition at line 910 of file pattern.c.

911 {
912  if (pat->min <= pat->max)
913  return;
914  int num = pat->min;
915  pat->min = pat->max;
916  pat->max = num;
917 }
int min
Definition: pattern.h:60
int max
Definition: pattern.h:61

+ Here is the caller graph for this function:

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

Parse a range given as a regex.

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

Definition at line 927 of file pattern.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

982 {
983  bool skip_quote = false;
984 
985  /* We need a Context for pretty much anything. */
986  if (!Context)
987  {
988  mutt_buffer_strcpy(err, _("No Context"));
989  return false;
990  }
991 
992  /* If simple_search is set to "~m %s", the range will have double quotes
993  * around it... */
994  if (*s->dptr == '"')
995  {
996  s->dptr++;
997  skip_quote = true;
998  }
999 
1000  for (int i_kind = 0; i_kind != RANGE_K_INVALID; i_kind++)
1001  {
1002  switch (eat_range_by_regex(pat, s, i_kind, err))
1003  {
1004  case RANGE_E_CTX:
1005  /* This means it matched syntactically but lacked context.
1006  * No point in continuing. */
1007  break;
1008  case RANGE_E_SYNTAX:
1009  /* Try another syntax, then */
1010  continue;
1011  case RANGE_E_OK:
1012  if (skip_quote && (*s->dptr == '"'))
1013  s->dptr++;
1014  SKIPWS(s->dptr);
1015  return true;
1016  }
1017  }
1018  return false;
1019 }
The "current" mailbox.
Definition: context.h:36
Range is valid.
Definition: pattern.c:121
Range contains syntax error.
Definition: pattern.c:122
#define _(a)
Definition: message.h:28
Range requires Context, but none available.
Definition: pattern.c:123
#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:149
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:927

+ Here is the call graph for this function:

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

1025 {
1026  struct Buffer *tmp = mutt_buffer_pool_get();
1027  bool rc = false;
1028 
1029  char *pexpr = s->dptr;
1031  {
1032  snprintf(err->data, err->dsize, _("Error in expression: %s"), pexpr);
1033  goto out;
1034  }
1035 
1036  if (mutt_buffer_is_empty(tmp))
1037  {
1038  snprintf(err->data, err->dsize, "%s", _("Empty expression"));
1039  goto out;
1040  }
1041 
1042  if (flags & MUTT_PC_PATTERN_DYNAMIC)
1043  {
1044  pat->dynamic = true;
1045  pat->p.str = mutt_str_strdup(tmp->data);
1046  }
1047 
1048  rc = eval_date_minmax(pat, tmp->data, err);
1049 
1050 out:
1052 
1053  return rc;
1054 }
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:83
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
#define MUTT_PC_PATTERN_DYNAMIC
Enable runtime date range evaluation.
Definition: pattern.h:44
size_t dsize
Length of data.
Definition: buffer.h:37
bool dynamic
evaluate date ranges at run time
Definition: pattern.h:58
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:2638
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:575
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:67
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:82

+ Here is the call graph for this function:

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

1064 {
1065  if (pat->ismulti)
1066  return (mutt_list_find(&pat->p.multi_cases, buf) != NULL);
1067  else if (pat->stringmatch)
1068  return pat->ign_case ? strcasestr(buf, pat->p.str) : strstr(buf, pat->p.str);
1069  else if (pat->groupmatch)
1070  return mutt_group_match(pat->p.group, buf);
1071  else
1072  return (regexec(pat->p.regex, buf, 0, NULL, 0) == 0);
1073 }
regex_t * regex
Definition: pattern.h:65
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:56
union Pattern::@2 p
char * str
Definition: pattern.h:67
struct Group * group
Definition: pattern.h:66
bool groupmatch
Definition: pattern.h:55
bool stringmatch
Definition: pattern.h:54
struct ListHead multi_cases
Definition: pattern.h:68
bool ismulti
multiple case (only for I pattern now)
Definition: pattern.h:59

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Search an email.

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

Definition at line 1083 of file pattern.c.

1084 {
1085  bool match = false;
1086  struct Message *msg = mx_msg_open(m, msgno);
1087  if (!msg)
1088  {
1089  return match;
1090  }
1091 
1092  FILE *fp = NULL;
1093  long lng = 0;
1094  struct Email *e = m->emails[msgno];
1095 #ifdef USE_FMEMOPEN
1096  char *temp = NULL;
1097  size_t tempsize;
1098 #else
1099  struct stat st;
1100 #endif
1101 
1102  if (C_ThoroughSearch)
1103  {
1104  /* decode the header / body */
1105  struct State s = { 0 };
1106  s.fp_in = msg->fp;
1107  s.flags = MUTT_CHARCONV;
1108 #ifdef USE_FMEMOPEN
1109  s.fp_out = open_memstream(&temp, &tempsize);
1110  if (!s.fp_out)
1111  {
1112  mutt_perror(_("Error opening 'memory stream'"));
1113  return false;
1114  }
1115 #else
1116  s.fp_out = mutt_file_mkstemp();
1117  if (!s.fp_out)
1118  {
1119  mutt_perror(_("Can't create temporary file"));
1120  return false;
1121  }
1122 #endif
1123 
1124  if (pat->op != MUTT_PAT_BODY)
1125  mutt_copy_header(msg->fp, e, s.fp_out, CH_FROM | CH_DECODE, NULL);
1126 
1127  if (pat->op != MUTT_PAT_HEADER)
1128  {
1130 
1131  if ((WithCrypto != 0) && (e->security & SEC_ENCRYPT) &&
1133  {
1134  mx_msg_close(m, &msg);
1135  if (s.fp_out)
1136  {
1138 #ifdef USE_FMEMOPEN
1139  FREE(&temp);
1140 #endif
1141  }
1142  return false;
1143  }
1144 
1145  fseeko(msg->fp, e->offset, SEEK_SET);
1146  mutt_body_handler(e->content, &s);
1147  }
1148 
1149 #ifdef USE_FMEMOPEN
1150  fclose(s.fp_out);
1151  lng = tempsize;
1152 
1153  if (tempsize)
1154  {
1155  fp = fmemopen(temp, tempsize, "r");
1156  if (!fp)
1157  {
1158  mutt_perror(_("Error re-opening 'memory stream'"));
1159  return false;
1160  }
1161  }
1162  else
1163  { /* fmemopen can't handle empty buffers */
1164  fp = mutt_file_fopen("/dev/null", "r");
1165  if (!fp)
1166  {
1167  mutt_perror(_("Error opening /dev/null"));
1168  return false;
1169  }
1170  }
1171 #else
1172  fp = s.fp_out;
1173  fflush(fp);
1174  fseek(fp, 0, SEEK_SET);
1175  fstat(fileno(fp), &st);
1176  lng = (long) st.st_size;
1177 #endif
1178  }
1179  else
1180  {
1181  /* raw header / body */
1182  fp = msg->fp;
1183  if (pat->op != MUTT_PAT_BODY)
1184  {
1185  fseeko(fp, e->offset, SEEK_SET);
1186  lng = e->content->offset - e->offset;
1187  }
1188  if (pat->op != MUTT_PAT_HEADER)
1189  {
1190  if (pat->op == MUTT_PAT_BODY)
1191  fseeko(fp, e->content->offset, SEEK_SET);
1192  lng += e->content->length;
1193  }
1194  }
1195 
1196  size_t blen = 256;
1197  char *buf = mutt_mem_malloc(blen);
1198 
1199  /* search the file "fp" */
1200  while (lng > 0)
1201  {
1202  if (pat->op == MUTT_PAT_HEADER)
1203  {
1204  buf = mutt_rfc822_read_line(fp, buf, &blen);
1205  if (*buf == '\0')
1206  break;
1207  }
1208  else if (!fgets(buf, blen - 1, fp))
1209  break; /* don't loop forever */
1210  if (patmatch(pat, buf))
1211  {
1212  match = true;
1213  break;
1214  }
1215  lng -= mutt_str_strlen(buf);
1216  }
1217 
1218  FREE(&buf);
1219 
1220  mx_msg_close(m, &msg);
1221 
1222  if (C_ThoroughSearch)
1223  {
1224  mutt_file_fclose(&fp);
1225 #ifdef USE_FMEMOPEN
1226  if (tempsize)
1227  FREE(&temp);
1228 #endif
1229  }
1230 
1231  return match;
1232 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
Pattern matches email&#39;s header.
Definition: pattern.h:124
The envelope/body of an email.
Definition: email.h:39
#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:92
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:48
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:122
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:391
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:1089
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:147
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:81
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:70
#define mutt_file_mkstemp()
Definition: file.h:105
short op
Definition: pattern.h:51
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/ncrypt.h pgplib.h, smime.h
Definition: email.h:41
LOFF_T offset
Where in the stream does this message begin?
Definition: email.h:85
Pattern matches email&#39;s body.
Definition: pattern.h:123
FILE * fp
pointer to the message data
Definition: mx.h:83
#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:1545
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:584
#define WithCrypto
Definition: ncrypt.h:160
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
return a stream pointer for a message
Definition: mx.c:1041
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:1063
int msgno
Number displayed to the user.
Definition: email.h:88
char * mutt_rfc822_read_line(FILE *fp, char *line, size_t *linelen)
Read a header line from a file.
Definition: parse.c:1056

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static const struct PatternFlags* lookup_tag ( char  tag)
static

Lookup a pattern modifier.

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

Definition at line 1298 of file pattern.c.

1299 {
1300  for (int i = 0; Flags[i].tag; i++)
1301  if (Flags[i].tag == tag)
1302  return &Flags[i];
1303  return NULL;
1304 }
int tag
character used to represent this op
Definition: pattern.c:177
static const struct PatternFlags Flags[]
Lookup table for all patterns.
Definition: pattern.c:1238

+ Here is the caller graph for this function:

static char* find_matching_paren ( char *  s)
static

Find the matching parenthesis.

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

Definition at line 1312 of file pattern.c.

1313 {
1314  int level = 1;
1315 
1316  for (; *s; s++)
1317  {
1318  if (*s == '(')
1319  level++;
1320  else if (*s == ')')
1321  {
1322  level--;
1323  if (level == 0)
1324  break;
1325  }
1326  }
1327  return s;
1328 }

+ Here is the caller graph for this function:

void mutt_pattern_free ( struct PatternHead **  pat)

Free a Pattern.

Parameters
[out]patPattern to free

Definition at line 1334 of file pattern.c.

1335 {
1336  if (!pat || !*pat)
1337  return;
1338 
1339  struct Pattern *np = SLIST_FIRST(*pat), *next = NULL;
1340 
1341  while (np)
1342  {
1343  next = SLIST_NEXT(np, entries);
1344 
1345  if (np->ismulti)
1347  else if (np->stringmatch || np->dynamic)
1348  FREE(&np->p.str);
1349  else if (np->groupmatch)
1350  np->p.group = NULL;
1351  else if (np->p.regex)
1352  {
1353  regfree(np->p.regex);
1354  FREE(&np->p.regex);
1355  }
1356 
1357  mutt_pattern_free(&np->child);
1358  FREE(&np);
1359 
1360  np = next;
1361  }
1362 
1363  FREE(pat);
1364 }
regex_t * regex
Definition: pattern.h:65
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:49
bool dynamic
evaluate date ranges at run time
Definition: pattern.h:58
#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:63
char * str
Definition: pattern.h:67
struct Group * group
Definition: pattern.h:66
#define FREE(x)
Definition: memory.h:40
bool groupmatch
Definition: pattern.h:55
bool stringmatch
Definition: pattern.h:54
struct ListHead multi_cases
Definition: pattern.h:68
bool ismulti
multiple case (only for I pattern now)
Definition: pattern.h:59
void mutt_pattern_free(struct PatternHead **pat)
Free a Pattern.
Definition: pattern.c:1334

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1371 {
1372  struct PatternHead *h = mutt_mem_calloc(1, sizeof(struct PatternHead));
1373  SLIST_INIT(h);
1374  struct Pattern *p = mutt_mem_calloc(1, sizeof(struct Pattern));
1375  SLIST_INSERT_HEAD(h, p, entries);
1376  return h;
1377 }
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:49
union Pattern::@2 p
#define SLIST_INSERT_HEAD(head, elm, field)
Definition: queue.h:265

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

struct PatternHead* mutt_pattern_comp ( const char *  s,
PatternCompFlags  flags,
struct Buffer err 
)

Create a Pattern.

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

Definition at line 1386 of file pattern.c.

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1645 {
1646  struct Pattern *p = NULL;
1647 
1648  SLIST_FOREACH(p, pat, entries)
1649  {
1650  if (mutt_pattern_exec(p, flags, m, e, cache) <= 0)
1651  return false;
1652  }
1653  return true;
1654 }
A simple (non-regex) pattern.
Definition: pattern.h:49
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:2002
union Pattern::@2 p
#define SLIST_FOREACH(var, head, field)
Definition: queue.h:231

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1667 {
1668  struct Pattern *p = NULL;
1669 
1670  SLIST_FOREACH(p, pat, entries)
1671  {
1672  if (mutt_pattern_exec(p, flags, m, e, cache) > 0)
1673  return true;
1674  }
1675  return false;
1676 }
A simple (non-regex) pattern.
Definition: pattern.h:49
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:2002
union Pattern::@2 p
#define SLIST_FOREACH(var, head, field)
Definition: queue.h:231

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Match a Pattern against and Address list.

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

Definition at line 1687 of file pattern.c.

1688 {
1689  va_list ap;
1690 
1691  va_start(ap, n);
1692  for (; n; n--)
1693  {
1694  struct AddressList *al = va_arg(ap, struct AddressList *);
1695  struct Address *a = NULL;
1696  TAILQ_FOREACH(a, al, entries)
1697  {
1698  if (pat->alladdr ^ ((!pat->isalias || mutt_alias_reverse_lookup(a)) &&
1699  ((a->mailbox && patmatch(pat, a->mailbox)) ||
1700  (match_personal && a->personal && patmatch(pat, a->personal)))))
1701  {
1702  va_end(ap);
1703  return !pat->alladdr; /* Found match, or non-match if alladdr */
1704  }
1705  }
1706  }
1707  va_end(ap);
1708  return pat->alladdr; /* No matches, or all matches if alladdr */
1709 }
#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:527
char * personal
Real name of address.
Definition: address.h:36
bool isalias
Definition: pattern.h:57
bool alladdr
Definition: pattern.h:53
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:1063

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Match references against a Pattern.

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

Definition at line 1717 of file pattern.c.

1718 {
1719  struct ListNode *np = NULL;
1720  STAILQ_FOREACH(np, refs, entries)
1721  {
1722  if (patmatch(pat, np->data))
1723  return true;
1724  }
1725  return false;
1726 }
#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:1063

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1746 {
1747  struct AddressList *als[] = { &e->to, &e->cc };
1748  for (size_t i = 0; i < mutt_array_size(als); ++i)
1749  {
1750  struct AddressList *al = als[i];
1751  struct Address *a = NULL;
1752  TAILQ_FOREACH(a, al, entries)
1753  {
1754  if (alladdr ^ p(a))
1755  return !alladdr;
1756  }
1757  }
1758  return alladdr;
1759 }
#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:59
struct AddressList to
Email&#39;s &#39;To&#39; list.
Definition: envelope.h:58

+ Here is the caller graph for this function:

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

1769 {
1771 }
bool mutt_is_subscribed_list(const struct Address *addr)
Is this the email address of a user-subscribed mailing list?
Definition: hdrline.c:113
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:1745

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1781 {
1782  return mutt_is_predicate_recipient(alladdr, e, &mutt_is_mail_list);
1783 }
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:101
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:1745

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1794 {
1795  struct Address *a = NULL;
1796  if (al1)
1797  {
1798  TAILQ_FOREACH(a, al1, entries)
1799  {
1800  if (alladdr ^ mutt_addr_is_user(a))
1801  return !alladdr;
1802  }
1803  }
1804 
1805  if (al2)
1806  {
1807  TAILQ_FOREACH(a, al2, entries)
1808  {
1809  if (alladdr ^ mutt_addr_is_user(a))
1810  return !alladdr;
1811  }
1812  }
1813  return alladdr;
1814 }
#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:668

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1832 {
1833  if (!t)
1834  return 0;
1835 
1836  int a;
1837  struct Email *e = t->message;
1838  if (e)
1839  if (mutt_pattern_exec(SLIST_FIRST(pat), flags, m, e, NULL))
1840  return 1;
1841 
1842  if (up && (a = match_threadcomplete(pat, flags, m, t->parent, 1, 1, 1, 0)))
1843  return a;
1844  if (right && t->parent && (a = match_threadcomplete(pat, flags, m, t->next, 0, 0, 1, 1)))
1845  {
1846  return a;
1847  }
1848  if (left && t->parent && (a = match_threadcomplete(pat, flags, m, t->prev, 1, 0, 0, 1)))
1849  {
1850  return a;
1851  }
1852  if (down && (a = match_threadcomplete(pat, flags, m, t->child, 1, 0, 1, 1)))
1853  return a;
1854  return 0;
1855 }
struct MuttThread * next
Next sibling Thread.
Definition: thread.h:47
The envelope/body of an email.
Definition: email.h:39
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:1829
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:2002
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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1869 {
1870  if (!t || !t->parent || !t->parent->message)
1871  return 0;
1872 
1873  return mutt_pattern_exec(SLIST_FIRST(pat), flags, m, t->parent->message, NULL);
1874 }
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:2002
#define SLIST_FIRST(head)
Definition: queue.h:229
struct Email * message
Email this Thread refers to.
Definition: thread.h:49

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1888 {
1889  if (!t || !t->child)
1890  return 0;
1891 
1892  for (t = t->child; t; t = t->next)
1893  if (t->message && mutt_pattern_exec(SLIST_FIRST(pat), flags, m, t->message, NULL))
1894  return 1;
1895 
1896  return 0;
1897 }
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:2002
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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1907 {
1908  if (!b)
1909  return false;
1910 
1911  char buf[256];
1912  snprintf(buf, sizeof(buf), "%s/%s", TYPE(b), b->subtype);
1913 
1914  if (patmatch(pat, buf))
1915  return true;
1916  if (match_content_type(pat, b->parts))
1917  return true;
1918  if (match_content_type(pat, b->next))
1919  return true;
1920  return false;
1921 }
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:1906
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:1063

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1930 {
1931  struct Buffer *err = mutt_buffer_pool_get();
1932 
1933  bool rc = eval_date_minmax(pat, pat->p.str, err);
1935 
1936  return rc;
1937 }
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:575
union Pattern::@2 p
char * str
Definition: pattern.h:67

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

1949 {
1951  return match_content_type(pat, e->content);
1952 }
struct Body * content
List of MIME parts.
Definition: email.h:92
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:48
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:1906

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Sets a value in the PatternCache cache entry.

Parameters
cache_entryCache entry to update
valueValue to set

Normalizes the "true" value to 2.

Definition at line 1961 of file pattern.c.

1962 {
1963  *cache_entry = (value != 0) ? 2 : 1;
1964 }

+ Here is the caller graph for this function:

static int get_pattern_cache_value ( int  cache_entry)
static

Get pattern cache value.

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

Definition at line 1972 of file pattern.c.

1973 {
1974  return cache_entry == 2;
1975 }

+ Here is the caller graph for this function:

static int is_pattern_cache_set ( int  cache_entry)
static

Is a given Pattern cached?

Parameters
cache_entryCache entry to check
Return values
trueIf it is cached

Definition at line 1982 of file pattern.c.

1983 {
1984  return cache_entry != 0;
1985 }

+ Here is the caller graph for this function:

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

2280 {
2281  mutt_buffer_reset(buf);
2282  mutt_buffer_addch(buf, '"');
2283  while (*str)
2284  {
2285  if ((*str == '\\') || (*str == '"'))
2286  mutt_buffer_addch(buf, '\\');
2287  mutt_buffer_addch(buf, *str++);
2288  }
2289  mutt_buffer_addch(buf, '"');
2290 }
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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

2298 {
2299  bool do_simple = true;
2300 
2301  for (const char *p = mutt_b2s(buf); p && (p[0] != '\0'); p++)
2302  {
2303  if ((p[0] == '\\') && (p[1] != '\0'))
2304  p++;
2305  else if ((p[0] == '~') || (p[0] == '=') || (p[0] == '%'))
2306  {
2307  do_simple = false;
2308  break;
2309  }
2310  }
2311 
2312  /* XXX - is mutt_str_strcasecmp() right here, or should we use locale's
2313  * equivalences? */
2314 
2315  if (do_simple) /* yup, so spoof a real request */
2316  {
2317  /* convert old tokens into the new format */
2318  if ((mutt_str_strcasecmp("all", mutt_b2s(buf)) == 0) ||
2319  (mutt_str_strcmp("^", mutt_b2s(buf)) == 0) ||
2320  (mutt_str_strcmp(".", mutt_b2s(buf)) == 0)) /* ~A is more efficient */
2321  {
2322  mutt_buffer_strcpy(buf, "~A");
2323  }
2324  else if (mutt_str_strcasecmp("del", mutt_b2s(buf)) == 0)
2325  mutt_buffer_strcpy(buf, "~D");
2326  else if (mutt_str_strcasecmp("flag", mutt_b2s(buf)) == 0)
2327  mutt_buffer_strcpy(buf, "~F");
2328  else if (mutt_str_strcasecmp("new", mutt_b2s(buf)) == 0)
2329  mutt_buffer_strcpy(buf, "~N");
2330  else if (mutt_str_strcasecmp("old", mutt_b2s(buf)) == 0)
2331  mutt_buffer_strcpy(buf, "~O");
2332  else if (mutt_str_strcasecmp("repl", mutt_b2s(buf)) == 0)
2333  mutt_buffer_strcpy(buf, "~Q");
2334  else if (mutt_str_strcasecmp("read", mutt_b2s(buf)) == 0)
2335  mutt_buffer_strcpy(buf, "~R");
2336  else if (mutt_str_strcasecmp("tag", mutt_b2s(buf)) == 0)
2337  mutt_buffer_strcpy(buf, "~T");
2338  else if (mutt_str_strcasecmp("unread", mutt_b2s(buf)) == 0)
2339  mutt_buffer_strcpy(buf, "~U");
2340  else
2341  {
2342  struct Buffer *tmp = mutt_buffer_pool_get();
2343  quote_simple(mutt_b2s(buf), tmp);
2344  mutt_file_expand_fmt(buf, simple, mutt_b2s(tmp));
2346  }
2347  }
2348 }
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:2279
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:41
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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static struct MuttThread* top_of_thread ( struct Email e)
static

Find the first email in the current thread.

Parameters
eCurrent Email
Return values
ptrSuccess, email found
NULLError

Definition at line 2356 of file pattern.c.

2357 {
2358  if (!e)
2359  return NULL;
2360 
2361  struct MuttThread *t = e->thread;
2362 
2363  while (t && t->parent)
2364  t = t->parent;
2365 
2366  return t;
2367 }
struct MuttThread * thread
Thread of Emails.
Definition: email.h:96
struct MuttThread * parent
Parent of this Thread.
Definition: thread.h:45
An Email conversation.
Definition: thread.h:34

+ Here is the caller graph for this function:

bool mutt_limit_current_thread ( struct Email e)

Limit the email view to the current thread.

Parameters
eCurrent Email
Return values
trueSuccess
falseFailure

Definition at line 2375 of file pattern.c.

2376 {
2377  if (!e)
2378  return false;
2379 
2380  struct MuttThread *me = top_of_thread(e);
2381  if (!me)
2382  return false;
2383 
2384  Context->mailbox->vcount = 0;
2385  Context->vsize = 0;
2386  Context->collapsed = false;
2387 
2388  for (int i = 0; i < Context->mailbox->msg_count; i++)
2389  {
2390  Context->mailbox->emails[i]->vnum = -1;
2391  Context->mailbox->emails[i]->limited = false;
2392  Context->mailbox->emails[i]->collapsed = false;
2393  Context->mailbox->emails[i]->num_hidden = 0;
2394 
2395  if (top_of_thread(Context->mailbox->emails[i]) == me)
2396  {
2397  struct Body *body = Context->mailbox->emails[i]->content;
2398 
2400  Context->mailbox->emails[i]->limited = true;
2402  Context->mailbox->vcount++;
2403  Context->vsize += (body->length + body->offset - body->hdr_offset);
2404  }
2405  }
2406  return true;
2407 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
int msg_count
Total number of messages.
Definition: mailbox.h:102
struct Body * content
List of MIME parts.
Definition: email.h:92
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
int vcount
The number of virtual messages.
Definition: mailbox.h:113
The body of an email.
Definition: body.h:34
struct Mailbox * mailbox
Definition: context.h:50
bool limited
Is this message in a limited view?
Definition: email.h:76
off_t vsize
Definition: context.h:38
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
static struct MuttThread * top_of_thread(struct Email *e)
Find the first email in the current thread.
Definition: pattern.c:2356
size_t num_hidden
Number of hidden messages in this view.
Definition: email.h:77
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:75
int vnum
Virtual message number.
Definition: email.h:89
An Email conversation.
Definition: thread.h:34
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
bool collapsed
Are all threads collapsed?
Definition: context.h:48
long hdr_offset
Offset in stream where the headers begin.
Definition: body.h:42

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_pattern_func ( int  op,
char *  prompt 
)

Perform some Pattern matching.

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

Definition at line 2416 of file pattern.c.

2417 {
2418  struct Buffer err;
2419  int rc = -1;
2420  struct Progress progress;
2421  struct Buffer *buf = mutt_buffer_pool_get();
2422 
2424  if (prompt || (op != MUTT_LIMIT))
2425  {
2426  if ((mutt_get_field(prompt, buf->data, buf->dsize, MUTT_PATTERN | MUTT_CLEAR) != 0) ||
2427  !(mutt_b2s(buf)[0]))
2428  {
2430  return -1;
2431  }
2432  }
2433  mutt_buffer_fix_dptr(buf);
2434 
2435  mutt_message(_("Compiling search pattern..."));
2436 
2437  char *simple = mutt_str_strdup(mutt_b2s(buf));
2439 
2440  mutt_buffer_init(&err);
2441  err.dsize = 256;
2442  err.data = mutt_mem_malloc(err.dsize);
2443  struct PatternHead *pat = mutt_pattern_comp(buf->data, MUTT_PC_FULL_MSG, &err);
2444  if (!pat)
2445  {
2446  mutt_error("%s", err.data);
2447  goto bail;
2448  }
2449 
2450 #ifdef USE_IMAP
2451  if ((Context->mailbox->magic == MUTT_IMAP) && (imap_search(Context->mailbox, pat) < 0))
2452  goto bail;
2453 #endif
2454 
2455  mutt_progress_init(&progress, _("Executing command on matching messages..."),
2457  (op == MUTT_LIMIT) ? Context->mailbox->msg_count :
2458  Context->mailbox->vcount);
2459 
2460  if (op == MUTT_LIMIT)
2461  {
2462  Context->mailbox->vcount = 0;
2463  Context->vsize = 0;
2464  Context->collapsed = false;
2465  int padding = mx_msg_padding_size(Context->mailbox);
2466 
2467  for (int i = 0; i < Context->mailbox->msg_count; i++)
2468  {
2469  mutt_progress_update(&progress, i, -1);
2470  /* new limit pattern implicitly uncollapses all threads */
2471  Context->mailbox->emails[i]->vnum = -1;
2472  Context->mailbox->emails[i]->limited = false;
2473  Context->mailbox->emails[i]->collapsed = false;
2474  Context->mailbox->emails[i]->num_hidden = 0;
2476  Context->mailbox, Context->mailbox->emails[i], NULL))
2477  {
2479  Context->mailbox->emails[i]->limited = true;
2481  Context->mailbox->vcount++;
2482  struct Body *b = Context->mailbox->emails[i]->content;
2483  Context->vsize += b->length + b->offset - b->hdr_offset + padding;
2484  }
2485  }
2486  }
2487  else
2488  {
2489  for (int i = 0; i < Context->mailbox->vcount; i++)
2490  {
2491  mutt_progress_update(&progress, i, -1);
2493  Context->mailbox->emails[Context->mailbox->v2r[i]], NULL))
2494  {
2495  switch (op)
2496  {
2497  case MUTT_UNDELETE:
2500  MUTT_PURGE, false);
2501  /* fallthrough */
2502  case MUTT_DELETE:
2505  MUTT_DELETE, (op == MUTT_DELETE));
2506  break;
2507  case MUTT_TAG:
2508  case MUTT_UNTAG:
2511  MUTT_TAG, (op == MUTT_TAG));
2512  break;
2513  }
2514  }
2515  }
2516  }
2517 
2518  mutt_clear_error();
2519 
2520  if (op == MUTT_LIMIT)
2521  {
2522  /* drop previous limit pattern */
2523  FREE(&Context->pattern);
2525 
2527  mutt_error(_("No messages matched criteria"));
2528 
2529  /* record new limit pattern, unless match all */
2530  const char *pbuf = buf->data;
2531  while (*pbuf == ' ')
2532  pbuf++;
2533  if (mutt_str_strcmp(pbuf, "~A") != 0)
2534  {
2535  Context->pattern = simple;
2536  simple = NULL; /* don't clobber it */
2538  }
2539  }
2540 
2541  rc = 0;
2542 
2543 bail:
2545  FREE(&simple);
2546  mutt_pattern_free(&pat);
2547  FREE(&err.data);
2548 
2549  return rc;
2550 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
#define MUTT_PROGRESS_MSG
message-based progress
Definition: progress.h:32
#define NONULL(x)
Definition: string2.h:37
int msg_count
Total number of messages.
Definition: mailbox.h:102
#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:69
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:2297
Messages in limited view.
Definition: mutt.h:110
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:92
void mutt_progress_update(struct Progress *progress, long pos, int percent)
Update the state of the progress bar.
Definition: progress.c:172
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:115
String manipulation buffer.
Definition: buffer.h:33
Messages to be un-deleted.
Definition: mutt.h:104
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:1349
#define _(a)
Definition: message.h:28
Messages to be purged (bypass trash)
Definition: mutt.h:105
A progress bar.
Definition: progress.h:37
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:71
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
int vcount
The number of virtual messages.
Definition: mailbox.h:113
The body of an email.
Definition: body.h:34
struct PatternHead * limit_pattern
Compiled limit pattern.
Definition: context.h:40
size_t dsize
Length of data.
Definition: buffer.h:37
struct Mailbox * mailbox
Definition: context.h:50
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:116
bool limited
Is this message in a limited view?
Definition: email.h:76
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:143
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:38
#define mutt_b2s(buf)
Definition: buffer.h:41
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:2002
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:103
struct PatternHead * mutt_pattern_comp(const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: pattern.c:1386
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:77
Tagged messages.
Definition: mutt.h:108
char * data
Pointer to data.
Definition: buffer.h:35
bool collapsed
Is this message part of a collapsed thread?
Definition: email.h:75
int vnum
Virtual message number.
Definition: email.h:89
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:75
WHERE char * C_SimpleSearch
Config: Pattern to search for when search doesn&#39;t contain ~&#39;s.
Definition: globals.h:147
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
bool collapsed
Are all threads collapsed?
Definition: context.h:48
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition: pattern.h:43
Messages to be un-tagged.
Definition: mutt.h:109
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size.
Definition: mx.c:1464
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:52
char * pattern
Limit pattern string.
Definition: context.h:39
static unsigned char * pbuf
Cache PGP data packet.
Definition: pgppacket.c:37
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:615
WHERE short C_ReadInc
Config: Update the progress bar after this many records read (0 to disable)
Definition: globals.h:157
void mutt_pattern_free(struct PatternHead **pat)
Free a Pattern.
Definition: pattern.c:1334

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int mutt_search_command ( int  cur,
int  op 
)

Perform a search.

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

Definition at line 2559 of file pattern.c.

2560 {
2561  struct Progress progress;
2562 
2563  if (!*LastSearch || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
2564  {
2565  char buf[256];
2566  mutt_str_strfcpy(buf, (LastSearch[0] != '\0') ? LastSearch : "", sizeof(buf));
2567  if ((mutt_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
2568  _("Search for: ") :
2569  _("Reverse search for: "),
2570  buf, sizeof(buf), MUTT_CLEAR | MUTT_PATTERN) != 0) ||
2571  !buf[0])
2572  {
2573  return -1;
2574  }
2575 
2576  if ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT))
2577  OptSearchReverse = false;
2578  else
2579  OptSearchReverse = true;
2580 
2581  /* compare the *expanded* version of the search pattern in case
2582  * $simple_search has changed while we were searching */
2583  struct Buffer *tmp = mutt_buffer_pool_get();
2584  mutt_buffer_strcpy(tmp, buf);
2586 
2587  if (!SearchPattern || (mutt_str_strcmp(mutt_b2s(tmp), LastSearchExpn) != 0))
2588  {
2589  struct Buffer err;
2590  mutt_buffer_init(&err);
2591  OptSearchInvalid = true;
2592  mutt_str_strfcpy(LastSearch, buf, sizeof(LastSearch));
2594  mutt_message(_("Compiling search pattern..."));
2596  err.dsize = 256;
2597  err.data = mutt_mem_malloc(err.dsize);
2599  if (!SearchPattern)
2600  {
2602  mutt_error("%s", err.data);
2603  FREE(&err.data);
2604  LastSearch[0] = '\0';
2605  LastSearchExpn[0] = '\0';
2606  return -1;
2607  }
2608  FREE(&err.data);
2609  mutt_clear_error();
2610  }
2611 
2613  }
2614 
2615  if (OptSearchInvalid)
2616  {
2617  for (int i = 0; i < Context->mailbox->msg_count; i++)
2618  Context->mailbox->emails[i]->searched = false;
2619 #ifdef USE_IMAP
2620  if ((Context->mailbox->magic == MUTT_IMAP) &&
2622  return -1;
2623 #endif
2624  OptSearchInvalid = false;
2625  }
2626 
2627  int incr = OptSearchReverse ? -1 : 1;
2628  if (op == OP_SEARCH_OPPOSITE)
2629  incr = -incr;
2630 
2631  mutt_progress_init(&progress, _("Searching..."), MUTT_PROGRESS_MSG, C_ReadInc,
2632  Context->mailbox->vcount);
2633 
2634  for (int i = cur + incr, j = 0; j != Context->mailbox->vcount; j++)
2635  {
2636  const char *msg = NULL;
2637  mutt_progress_update(&progress, j, -1);
2638  if (i > Context->mailbox->vcount - 1)
2639  {
2640  i = 0;
2641  if (C_WrapSearch)
2642  msg = _("Search wrapped to top");
2643  else
2644  {
2645  mutt_message(_("Search hit bottom without finding match"));
2646  return -1;
2647  }
2648  }
2649  else if (i < 0)
2650  {
2651  i = Context->mailbox->vcount - 1;
2652  if (C_WrapSearch)
2653  msg = _("Search wrapped to bottom");
2654  else
2655  {
2656  mutt_message(_("Search hit top without finding match"));
2657  return -1;
2658  }
2659  }
2660 
2661  struct Email *e = Context->mailbox->emails[Context->mailbox->v2r[i]];
2662  if (e->searched)
2663  {
2664  /* if we've already evaluated this message, use the cached value */
2665  if (e->matched)
2666  {
2667  mutt_clear_error();
2668  if (msg && *msg)
2669  mutt_message(msg);
2670  return i;
2671  }
2672  }
2673  else
2674  {
2675  /* remember that we've already searched this message */
2676  e->searched = true;
2678  Context->mailbox, e, NULL);
2679  if (e->matched > 0)
2680  {
2681  mutt_clear_error();
2682  if (msg && *msg)
2683  mutt_message(msg);
2684  return i;
2685  }
2686  }
2687 
2688  if (SigInt)
2689  {
2690  mutt_error(_("Search interrupted"));
2691  SigInt = 0;
2692  return -1;
2693  }
2694 
2695  i += incr;
2696  }
2697 
2698  mutt_error(_("Not found"));
2699  return -1;
2700 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:110
The "current" mailbox.
Definition: context.h:36
#define MUTT_PROGRESS_MSG
message-based progress
Definition: progress.h:32
#define NONULL(x)
Definition: string2.h:37
int msg_count
Total number of messages.
Definition: mailbox.h:102
The envelope/body of an email.
Definition: email.h:39
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:69
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:2297
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
void mutt_progress_update(struct Progress *progress, long pos, int percent)
Update the state of the progress bar.
Definition: progress.c:172
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:115
String manipulation buffer.
Definition: buffer.h:33
int imap_search(struct Mailbox *m, const struct PatternHead *pat)
Find a matching mailbox.
Definition: imap.c:1349
#define _(a)
Definition: message.h:28
static char LastSearch[256]
last pattern searched for
Definition: pattern.c:199
WHERE bool C_WrapSearch
Config: Wrap around when the search hits the end.
Definition: globals.h:276
bool searched
Email has been searched.
Definition: email.h:69
A progress bar.
Definition: progress.h:37
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:71
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
int vcount
The number of virtual messages.
Definition: mailbox.h:113
struct Mailbox * mailbox
Definition: context.h:50
enum MailboxType magic
Mailbox type.
Definition: mailbox.h:116
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:143
#define mutt_b2s(buf)
Definition: buffer.h:41
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:2002
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:200
#define SLIST_FIRST(head)
Definition: queue.h:229
struct PatternHead * mutt_pattern_comp(const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: pattern.c:1386
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:50
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:75
WHERE char * C_SimpleSearch
Config: Pattern to search for when search doesn&#39;t contain ~&#39;s.
Definition: globals.h:147
int * v2r
Mapping from virtual to real msgno.
Definition: mailbox.h:112
static struct PatternHead * SearchPattern
current search pattern
Definition: pattern.c:198
#define mutt_error(...)
Definition: logging.h:84
#define FREE(x)
Definition: memory.h:40
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition: pattern.h:43
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:61
&#39;IMAP&#39; Mailbox type
Definition: mailbox.h:52
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:51
WHERE short C_ReadInc
Config: Update the progress bar after this many records read (0 to disable)
Definition: globals.h:157
bool matched
Search matches this Email.
Definition: email.h:70
void mutt_pattern_free(struct PatternHead **pat)
Free a Pattern.
Definition: pattern.c:1334

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

bool C_ThoroughSearch

Config: Decode headers and messages before searching them.

Definition at line 70 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:147
#define RANGE_REL_RX
Definition: pattern.c:76
#define RANGE_ABS_RX
Definition: pattern.c:80
Greater-than range.
Definition: pattern.c:146
#define RANGE_LT_RX
Definition: pattern.c:83
#define RANGE_BARE_RX
Definition: pattern.c:87
Absolute range.
Definition: pattern.c:144
#define RANGE_GT_RX
Definition: pattern.c:84
Less-than range.
Definition: pattern.c:145
Relative range.
Definition: pattern.c:143

Set of Regexes for various range types.

This array, will also contain the compiled regexes.

Definition at line 189 of file pattern.c.

struct PatternHead* SearchPattern = NULL
static

current search pattern

Definition at line 198 of file pattern.c.

char LastSearch[256] = { 0 }
static

last pattern searched for

Definition at line 199 of file pattern.c.

char LastSearchExpn[1024] = { 0 }
static

expanded version of LastSearch

Definition at line 200 of file pattern.c.

const struct PatternFlags Flags[]
static

Lookup table for all patterns.

Definition at line 1238 of file pattern.c.