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

Match patterns to emails. More...

#include "config.h"
#include <stddef.h>
#include <ctype.h>
#include <regex.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include "mutt/mutt.h"
#include "address/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "conn/conn.h"
#include "mutt.h"
#include "pattern.h"
#include "alias.h"
#include "context.h"
#include "copy.h"
#include "curs_lib.h"
#include "filter.h"
#include "globals.h"
#include "handler.h"
#include "hdrline.h"
#include "mailbox.h"
#include "mutt_logging.h"
#include "mutt_menu.h"
#include "mutt_parse.h"
#include "muttlib.h"
#include "mx.h"
#include "ncrypt/ncrypt.h"
#include "opcodes.h"
#include "options.h"
#include "progress.h"
#include "protos.h"
#include "state.h"
#include "imap/imap.h"
+ 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 PatternFlags
 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...
 

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 (char *s, int flags, struct Buffer *err)
 Create a Pattern. More...
 
static bool perform_and (struct PatternHead *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
 Perform a logical AND on a set of Patterns. More...
 
static int perform_or (struct PatternHead *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
 Perform a logical OR on a set of Patterns. More...
 
static int match_addrlist (struct Pattern *pat, bool match_personal, int n,...)
 Match a Pattern against and Address list. More...
 
static bool match_reference (struct Pattern *pat, struct ListHead *refs)
 Match references against a Pattern. More...
 
int mutt_is_list_recipient (bool alladdr, struct Address *a1, struct Address *a2)
 Matches subscribed mailing lists. More...
 
int mutt_is_list_cc (int alladdr, struct Address *a1, struct Address *a2)
 Matches known mailing lists. More...
 
static int match_user (int alladdr, struct Address *a1, struct Address *a2)
 Matches the user's email Address. More...
 
static int match_threadcomplete (struct 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

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

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

Definition at line 77 of file pattern.c.

#define RANGE_REL_RX   "^" RANGE_REL_SLOT_RX "," RANGE_REL_SLOT_RX

Definition at line 78 of file pattern.c.

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

Definition at line 81 of file pattern.c.

#define RANGE_ABS_RX   "^" RANGE_ABS_SLOT_RX "-" RANGE_ABS_SLOT_RX

Definition at line 82 of file pattern.c.

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

Definition at line 85 of file pattern.c.

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

Definition at line 86 of file pattern.c.

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

Definition at line 89 of file pattern.c.

#define RANGE_RX_GROUPS   5

Definition at line 90 of file pattern.c.

#define KILO   1024

Definition at line 92 of file pattern.c.

#define MEGA   1048576

Definition at line 93 of file pattern.c.

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

Definition at line 94 of file pattern.c.

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

Definition at line 95 of file pattern.c.

#define MUTT_MAXRANGE   -1

Definition at line 98 of file pattern.c.

#define MUTT_PDR_NO_FLAGS   0

No flags are set.

Definition at line 101 of file pattern.c.

#define MUTT_PDR_MINUS   (1 << 0)

Pattern contains a range.

Definition at line 102 of file pattern.c.

#define MUTT_PDR_PLUS   (1 << 1)

Extend the range using '+'.

Definition at line 103 of file pattern.c.

#define MUTT_PDR_WINDOW   (1 << 2)

Extend the range in both directions using '*'.

Definition at line 104 of file pattern.c.

#define MUTT_PDR_ABSOLUTE   (1 << 3)

Absolute pattern range.

Definition at line 105 of file pattern.c.

#define MUTT_PDR_DONE   (1 << 4)

Pattern parse successfully.

Definition at line 106 of file pattern.c.

#define MUTT_PDR_ERROR   (1 << 8)

Invalid pattern.

Definition at line 107 of file pattern.c.

#define MUTT_PDR_ERRORDONE   (MUTT_PDR_ERROR | MUTT_PDR_DONE)

Definition at line 109 of file pattern.c.

#define RANGE_DOT   '.'

Definition at line 111 of file pattern.c.

#define RANGE_CIRCUM   '^'

Definition at line 112 of file pattern.c.

#define RANGE_DOLLAR   '$'

Definition at line 113 of file pattern.c.

#define RANGE_LT   '<'

Definition at line 114 of file pattern.c.

#define RANGE_GT   '>'

Definition at line 115 of file pattern.c.

Typedef Documentation

typedef uint16_t PatternFlags

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

Definition at line 100 of file pattern.c.

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

typedef pattern_eat_t - Parse a pattern

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

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

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

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

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

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

208 {
209  struct Buffer buf;
210 
211  mutt_buffer_init(&buf);
212  char *pexpr = s->dptr;
213  if ((mutt_extract_token(&buf, s, MUTT_TOKEN_PATTERN | MUTT_TOKEN_COMMENT) != 0) || !buf.data)
214  {
215  mutt_buffer_printf(err, _("Error in expression: %s"), pexpr);
216  FREE(&buf.data);
217  return false;
218  }
219  if (buf.data[0] == '\0')
220  {
221  mutt_buffer_printf(err, "%s", _("Empty expression"));
222  FREE(&buf.data);
223  return false;
224  }
225 
226  if (pat->stringmatch)
227  {
228  pat->p.str = mutt_str_strdup(buf.data);
229  pat->ign_case = mutt_mb_is_lower(buf.data);
230  FREE(&buf.data);
231  }
232  else if (pat->groupmatch)
233  {
234  pat->p.group = mutt_pattern_group(buf.data);
235  FREE(&buf.data);
236  }
237  else
238  {
239  pat->p.regex = mutt_mem_malloc(sizeof(regex_t));
240  int case_flags = mutt_mb_is_lower(buf.data) ? REG_ICASE : 0;
241  int rc = REG_COMP(pat->p.regex, buf.data, REG_NEWLINE | REG_NOSUB | case_flags);
242  if (rc != 0)
243  {
244  char errmsg[256];
245  regerror(rc, pat->p.regex, errmsg, sizeof(errmsg));
246  mutt_buffer_add_printf(err, "'%s': %s", buf.data, errmsg);
247  FREE(&buf.data);
248  FREE(&pat->p.regex);
249  return false;
250  }
251  FREE(&buf.data);
252  }
253 
254  return true;
255 }
regex_t * regex
Definition: pattern.h:62
#define MUTT_TOKEN_COMMENT
Don&#39;t reap comments.
Definition: mutt.h:81
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200
#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:242
bool ign_case
ignore case for local stringmatch searches
Definition: pattern.h:53
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:2656
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:97
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:64
struct Group * group
Definition: pattern.h:63
#define FREE(x)
Definition: memory.h:40
bool groupmatch
Definition: pattern.h:52
bool stringmatch
Definition: pattern.h:51
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:68
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:80
struct Group * mutt_pattern_group(const char *pat)
Match a pattern to a Group.
Definition: group.c:64

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

262 {
263  struct ListHead *msgid_list = (struct ListHead *) (user_data);
264  char *nows = mutt_str_skip_whitespace(line);
265  if (!*nows)
266  return true;
268  mutt_list_insert_tail(msgid_list, mutt_str_strdup(nows));
269  return true;
270 }
char * mutt_str_skip_whitespace(char *p)
Find the first non-whitespace character in a string.
Definition: string.c:723
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:61
void mutt_str_remove_trailing_ws(char *s)
Trim trailing whitespace from a string.
Definition: string.c:737
const char * line
Definition: common.c:35
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 275 of file pattern.c.

276 {
277  struct Buffer cmd_buf;
278  struct Buffer tok_buf;
279  FILE *fp = NULL;
280 
282  {
283  mutt_buffer_printf(err, "%s", _("No search command defined"));
284  return false;
285  }
286 
287  mutt_buffer_init(&tok_buf);
288  char *pexpr = s->dptr;
289  if ((mutt_extract_token(&tok_buf, s, MUTT_TOKEN_PATTERN | MUTT_TOKEN_COMMENT) != 0) ||
290  !tok_buf.data)
291  {
292  mutt_buffer_printf(err, _("Error in expression: %s"), pexpr);
293  return false;
294  }
295  if (*tok_buf.data == '\0')
296  {
297  mutt_buffer_printf(err, "%s", _("Empty expression"));
298  FREE(&tok_buf.data);
299  return false;
300  }
301 
302  mutt_buffer_init(&cmd_buf);
304  mutt_buffer_addch(&cmd_buf, ' ');
305  if (!Context || !Context->mailbox)
306  {
307  mutt_buffer_addch(&cmd_buf, '/');
308  }
309  else
310  {
311  char *escaped_folder = mutt_path_escape(mutt_b2s(Context->mailbox->pathbuf));
312  mutt_debug(LL_DEBUG2, "escaped folder path: %s\n", escaped_folder);
313  mutt_buffer_addch(&cmd_buf, '\'');
314  mutt_buffer_addstr(&cmd_buf, escaped_folder);
315  mutt_buffer_addch(&cmd_buf, '\'');
316  }
317  mutt_buffer_addch(&cmd_buf, ' ');
318  mutt_buffer_addstr(&cmd_buf, tok_buf.data);
319  FREE(&tok_buf.data);
320 
321  mutt_message(_("Running search command: %s ..."), cmd_buf.data);
322  pat->ismulti = true;
324  pid_t pid = mutt_create_filter(cmd_buf.data, NULL, &fp, NULL);
325  if (pid < 0)
326  {
327  mutt_buffer_printf(err, "unable to fork command: %s\n", cmd_buf.data);
328  FREE(&cmd_buf.data);
329  return false;
330  }
331 
333  mutt_file_fclose(&fp);
334  mutt_wait_filter(pid);
335  FREE(&cmd_buf.data);
336  return true;
337 }
pid_t mutt_create_filter(const char *s, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:216
The "current" mailbox.
Definition: context.h:38
#define mutt_message(...)
Definition: logging.h:82
#define MUTT_TOKEN_COMMENT
Don&#39;t reap comments.
Definition: mutt.h:81
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200
struct Mailbox * mailbox
Definition: context.h:52
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:757
char * mutt_path_escape(const char *src)
Escapes single quotes in a path for a command string.
Definition: path.c:555
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:264
#define mutt_b2s(buf)
Definition: buffer.h:42
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:2656
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:279
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:261
struct Buffer * pathbuf
Definition: mailbox.h:85
union Pattern::@2 p
#define FREE(x)
Definition: memory.h:40
struct ListHead multi_cases
Definition: pattern.h:65
#define mutt_debug(LEVEL,...)
Definition: logging.h:80
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:68
WHERE char * C_ExternalSearchCommand
Config: External search command.
Definition: globals.h:105
void mutt_list_clear(struct ListHead *h)
Free a list, but NOT its strings.
Definition: list.c:160
int mutt_wait_filter(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:227
#define MUTT_TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition: mutt.h:80
bool ismulti
multiple case (only for I pattern now)
Definition: pattern.h:56

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

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

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

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

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Parse a date range.

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

Definition at line 453 of file pattern.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

913 {
914  if (pat->min <= pat->max)
915  return;
916  int num = pat->min;
917  pat->min = pat->max;
918  pat->max = num;
919 }
int min
Definition: pattern.h:57
int max
Definition: pattern.h:58

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

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

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

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

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

1027 {
1028  struct Buffer *tmp = mutt_buffer_pool_get();
1029  bool rc = false;
1030 
1031  char *pexpr = s->dptr;
1033  {
1034  snprintf(err->data, err->dsize, _("Error in expression: %s"), pexpr);
1035  goto out;
1036  }
1037 
1038  if (mutt_buffer_is_empty(tmp))
1039  {
1040  snprintf(err->data, err->dsize, "%s", _("Empty expression"));
1041  goto out;
1042  }
1043 
1044  if (flags & MUTT_PATTERN_DYNAMIC)
1045  {
1046  pat->dynamic = true;
1047  pat->p.str = mutt_str_strdup(tmp->data);
1048  }
1049 
1050  rc = eval_date_minmax(pat, tmp->data, err);
1051 
1052 out:
1054 
1055  return rc;
1056 }
#define MUTT_TOKEN_COMMENT
Don&#39;t reap comments.
Definition: mutt.h:81
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
size_t dsize
length of data
Definition: buffer.h:37
bool dynamic
evaluate date ranges at run time
Definition: pattern.h:55
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:2656
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:577
char * dptr
current read/write position
Definition: buffer.h:36
char * data
pointer to data
Definition: buffer.h:35
#define MUTT_PATTERN_DYNAMIC
enable runtime date range evaluation
Definition: pattern.h:41
union Pattern::@2 p
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
char * str
Definition: pattern.h:64
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:409
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:291
#define MUTT_TOKEN_PATTERN
~%=!| are terms (for patterns)
Definition: mutt.h:80
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:398

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

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

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

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

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

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

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

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

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

1337 {
1338  if (!pat || !*pat)
1339  return;
1340 
1341  struct Pattern *np = SLIST_FIRST(*pat), *next = NULL;
1342 
1343  while (np)
1344  {
1345  next = SLIST_NEXT(np, entries);
1346 
1347  if (np->ismulti)
1349  else if (np->stringmatch || np->dynamic)
1350  FREE(&np->p.str);
1351  else if (np->groupmatch)
1352  np->p.group = NULL;
1353  else if (np->p.regex)
1354  {
1355  regfree(np->p.regex);
1356  FREE(&np->p.regex);
1357  }
1358 
1359  mutt_pattern_free(&np->child);
1360  FREE(&np);
1361 
1362  np = next;
1363  }
1364 
1365  FREE(pat);
1366 }
regex_t * regex
Definition: pattern.h:62
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:117
A simple (non-regex) pattern.
Definition: pattern.h:46
bool dynamic
evaluate date ranges at run time
Definition: pattern.h:55
#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:60
char * str
Definition: pattern.h:64
struct Group * group
Definition: pattern.h:63
#define FREE(x)
Definition: memory.h:40
bool groupmatch
Definition: pattern.h:52
bool stringmatch
Definition: pattern.h:51
struct ListHead multi_cases
Definition: pattern.h:65
bool ismulti
multiple case (only for I pattern now)
Definition: pattern.h:56
void mutt_pattern_free(struct PatternHead **pat)
Free a Pattern.
Definition: pattern.c:1336

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

1373 {
1374  struct PatternHead *h = mutt_mem_calloc(1, sizeof(struct PatternHead));
1375  SLIST_INIT(h);
1376  struct Pattern *p = mutt_mem_calloc(1, sizeof(struct Pattern));
1377  SLIST_INSERT_HEAD(h, p, entries);
1378  return h;
1379 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:51
#define SLIST_INIT(head)
Definition: queue.h:256
A simple (non-regex) pattern.
Definition: pattern.h:46
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 ( char *  s,
int  flags,
struct Buffer err 
)

Create a Pattern.

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

Definition at line 1388 of file pattern.c.

1389 {
1390  /* curlist when assigned will always point to a list containing at least one node
1391  * with a Pattern value. */
1392  struct PatternHead *curlist = NULL;
1393  struct PatternHead *tmp = NULL, *tmp2 = NULL;
1394  struct PatternHead *last = NULL;
1395  bool not = false;
1396  bool alladdr = false;
1397  bool or = false;
1398  bool implicit = true; /* used to detect logical AND operator */
1399  bool isalias = false;
1400  short thread_op;
1401  const struct PatternFlags *entry = NULL;
1402  char *p = NULL;
1403  char *buf = NULL;
1404  struct Buffer ps;
1405 
1406  mutt_buffer_init(&ps);
1407  ps.dptr = s;
1408  ps.dsize = mutt_str_strlen(s);
1409 
1410  while (*ps.dptr)
1411  {
1412  SKIPWS(ps.dptr);
1413  switch (*ps.dptr)
1414  {
1415  case '^':
1416  ps.dptr++;
1417  alladdr = !alladdr;
1418  break;
1419  case '!':
1420  ps.dptr++;
1421  not = !not;
1422  break;
1423  case '@':
1424  ps.dptr++;
1425  isalias = !isalias;
1426  break;
1427  case '|':
1428  if (! or)
1429  {
1430  if (!curlist)
1431  {
1432  mutt_buffer_printf(err, _("error in pattern at: %s"), ps.dptr);
1433  return NULL;
1434  }
1435 
1436  struct Pattern *pat = SLIST_FIRST(curlist);
1437 
1438  if (SLIST_NEXT(pat, entries))
1439  {
1440  /* A & B | C == (A & B) | C */
1441  tmp = mutt_pattern_node_new();
1442  pat = SLIST_FIRST(tmp);
1443  pat->op = MUTT_PAT_AND;
1444  pat->child = curlist;
1445 
1446  curlist = tmp;
1447  last = curlist;
1448  }
1449 
1450  or = true;
1451  }
1452  ps.dptr++;
1453  implicit = false;
1454  not = false;
1455  alladdr = false;
1456  isalias = false;
1457  break;
1458  case '%':
1459  case '=':
1460  case '~':
1461  {
1462  struct Pattern *pat = NULL;
1463  if (!*(ps.dptr + 1))
1464  {
1465  mutt_buffer_printf(err, _("missing pattern: %s"), ps.dptr);
1466  goto cleanup;
1467  }
1468  thread_op = 0;
1469  if (*(ps.dptr + 1) == '(')
1470  thread_op = MUTT_PAT_THREAD;
1471  else if ((*(ps.dptr + 1) == '<') && (*(ps.dptr + 2) == '('))
1472  thread_op = MUTT_PAT_PARENT;
1473  else if ((*(ps.dptr + 1) == '>') && (*(ps.dptr + 2) == '('))
1474  thread_op = MUTT_PAT_CHILDREN;
1475  if (thread_op)
1476  {
1477  ps.dptr++; /* skip ~ */
1478  if ((thread_op == MUTT_PAT_PARENT) || (thread_op == MUTT_PAT_CHILDREN))
1479  ps.dptr++;
1480  p = find_matching_paren(ps.dptr + 1);
1481  if (*p != ')')
1482  {
1483  mutt_buffer_printf(err, _("mismatched parentheses: %s"), ps.dptr);
1484  goto cleanup;
1485  }
1486  tmp = mutt_pattern_node_new();
1487  pat = SLIST_FIRST(tmp);
1488  pat->op = thread_op;
1489  if (last)
1490  SLIST_NEXT(SLIST_FIRST(last), entries) = pat;
1491  else
1492  curlist = tmp;
1493  last = tmp;
1494  pat->not ^= not;
1495  pat->alladdr |= alladdr;
1496  pat->isalias |= isalias;
1497  not = false;
1498  alladdr = false;
1499  isalias = false;
1500  /* compile the sub-expression */
1501  buf = mutt_str_substr_dup(ps.dptr + 1, p);
1502  tmp2 = mutt_pattern_comp(buf, flags, err);
1503  if (!tmp2)
1504  {
1505  FREE(&buf);
1506  goto cleanup;
1507  }
1508  FREE(&buf);
1509  pat->child = tmp2;
1510  ps.dptr = p + 1; /* restore location */
1511  break;
1512  }
1513  if (implicit && or)
1514  {
1515  /* A | B & C == (A | B) & C */
1516  tmp = mutt_pattern_node_new();
1517  pat = SLIST_FIRST(tmp);
1518  pat->op = MUTT_PAT_OR;
1519  pat->child = curlist;
1520  curlist = tmp;
1521  last = tmp;
1522  or = false;
1523  }
1524 
1525  tmp = mutt_pattern_node_new();
1526  pat = SLIST_FIRST(tmp);
1527  pat->not = not;
1528  pat->alladdr = alladdr;
1529  pat->isalias = isalias;
1530  pat->stringmatch = (*ps.dptr == '=');
1531  pat->groupmatch = (*ps.dptr == '%');
1532  not = false;
1533  alladdr = false;
1534  isalias = false;
1535 
1536  if (last)
1537  SLIST_NEXT(SLIST_FIRST(last), entries) = pat;
1538  else
1539  curlist = tmp;
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->class && ((flags & entry->class) == 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)
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 != ')')
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->not ^= not;
1597  pat->alladdr |= alladdr;
1598  pat->isalias |= isalias;
1599  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 (SLIST_NEXT(SLIST_FIRST(curlist), entries))
1617  {
1618  tmp = mutt_pattern_node_new();
1619  struct Pattern *pat = SLIST_FIRST(tmp);
1620  pat->op = or ? MUTT_PAT_OR : MUTT_PAT_AND;
1621  pat->child = curlist;
1622  curlist = tmp;
1623  }
1624 
1625  return curlist;
1626 
1627 cleanup:
1628  mutt_pattern_free(&curlist);
1629  return NULL;
1630 }
pattern_eat_t * eat_arg
Callback function to parse the argument.
Definition: pattern.c:182
bool not
Definition: pattern.h:49
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:1314
size_t mutt_str_strlen(const char *a)
Calculate the length of a string, safely.
Definition: string.c:669
Pattern matches a child email.
Definition: pattern.h:107
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:200
A simple (non-regex) pattern.
Definition: pattern.h:46
int op
operation to perform
Definition: pattern.c:180
static const struct PatternFlags * lookup_tag(char tag)
Lookup a pattern modifier.
Definition: pattern.c:1300
#define SKIPWS(ch)
Definition: string2.h:46
#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:322
static struct PatternHead * mutt_pattern_node_new(void)
Create a new list containing a Pattern.
Definition: pattern.c:1372
#define SLIST_FIRST(head)
Definition: queue.h:229
Either pattern can match.
Definition: pattern.h:104
struct PatternHead * mutt_pattern_comp(char *s, int flags, struct Buffer *err)
Create a Pattern.
Definition: pattern.c:1388
int class
Pattern class, e.g. MUTT_FULL_MSG.
Definition: pattern.c:181
short op
Definition: pattern.h:48
Pattern matches parent.
Definition: pattern.h:106
bool isalias
Definition: pattern.h:54
struct PatternHead * child
arguments to logical op
Definition: pattern.h:60
Both patterns must match.
Definition: pattern.h:103
#define FREE(x)
Definition: memory.h:40
bool groupmatch
Definition: pattern.h:52
bool stringmatch
Definition: pattern.h:51
bool alladdr
Definition: pattern.h:50
Pattern matches email thread.
Definition: pattern.h:105
Mapping between user character and internal constant.
Definition: pattern.c:177
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:68
char * mutt_str_substr_dup(const char *begin, const char *end)
Duplicate a sub-string.
Definition: string.c:582
void mutt_pattern_free(struct PatternHead **pat)
Free a Pattern.
Definition: pattern.c:1336

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

1643 {
1644  struct Pattern *p = NULL;
1645 
1646  SLIST_FOREACH(p, pat, entries)
1647  {
1648  if (mutt_pattern_exec(p, flags, m, e, cache) <= 0)
1649  return false;
1650  }
1651  return true;
1652 }
A simple (non-regex) pattern.
Definition: pattern.h:46
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:1970
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 1663 of file pattern.c.

1665 {
1666  struct Pattern *p = NULL;
1667 
1668  SLIST_FOREACH(p, pat, entries)
1669  {
1670  if (mutt_pattern_exec(p, flags, m, e, cache) > 0)
1671  return true;
1672  }
1673  return false;
1674 }
A simple (non-regex) pattern.
Definition: pattern.h:46
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:1970
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 1685 of file pattern.c.

1686 {
1687  va_list ap;
1688 
1689  va_start(ap, n);
1690  for (; n; n--)
1691  {
1692  for (struct Address *a = va_arg(ap, struct Address *); a; a = a->next)
1693  {
1694  if (pat->alladdr ^ ((!pat->isalias || mutt_alias_reverse_lookup(a)) &&
1695  ((a->mailbox && patmatch(pat, a->mailbox)) ||
1696  (match_personal && a->personal && patmatch(pat, a->personal)))))
1697  {
1698  va_end(ap);
1699  return !pat->alladdr; /* Found match, or non-match if alladdr */
1700  }
1701  }
1702  }
1703  va_end(ap);
1704  return pat->alladdr; /* No matches, or all matches if alladdr */
1705 }
struct Address * mutt_alias_reverse_lookup(struct Address *a)
Does the user have an alias for the given address.
Definition: alias.c:538
An email address.
Definition: address.h:32
bool isalias
Definition: pattern.h:54
bool alladdr
Definition: pattern.h:50
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:1065
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Match references against a Pattern.

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

Definition at line 1713 of file pattern.c.

1714 {
1715  struct ListNode *np = NULL;
1716  STAILQ_FOREACH(np, refs, entries)
1717  {
1718  if (patmatch(pat, np->data))
1719  return true;
1720  }
1721  return false;
1722 }
#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:1065

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Matches subscribed mailing lists.

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

Definition at line 1732 of file pattern.c.

1733 {
1734  for (; a1; a1 = a1->next)
1735  if (alladdr ^ mutt_is_subscribed_list(a1))
1736  return !alladdr;
1737  for (; a2; a2 = a2->next)
1738  if (alladdr ^ mutt_is_subscribed_list(a2))
1739  return !alladdr;
1740  return alladdr;
1741 }
bool mutt_is_subscribed_list(struct Address *addr)
Is this the email address of a user-subscribed mailing list?
Definition: hdrline.c:113
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Matches known mailing lists.

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

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

Definition at line 1754 of file pattern.c.

1755 {
1756  for (; a1; a1 = a1->next)
1757  if (alladdr ^ mutt_is_mail_list(a1))
1758  return !alladdr;
1759  for (; a2; a2 = a2->next)
1760  if (alladdr ^ mutt_is_mail_list(a2))
1761  return !alladdr;
1762  return alladdr;
1763 }
bool mutt_is_mail_list(struct Address *addr)
Is this the email address of a mailing list?
Definition: hdrline.c:101
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

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

Matches the user's email Address.

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

Definition at line 1773 of file pattern.c.

1774 {
1775  for (; a1; a1 = a1->next)
1776  if (alladdr ^ mutt_addr_is_user(a1))
1777  return !alladdr;
1778  for (; a2; a2 = a2->next)
1779  if (alladdr ^ mutt_addr_is_user(a2))
1780  return !alladdr;
1781  return alladdr;
1782 }
bool mutt_addr_is_user(struct Address *addr)
Does the address belong to the user.
Definition: alias.c:677
struct Address * next
Definition: address.h:39

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int match_threadcomplete ( struct 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 1797 of file pattern.c.

1800 {
1801  if (!t)
1802  return 0;
1803 
1804  int a;
1805  struct Email *e = t->message;
1806  if (e)
1807  if (mutt_pattern_exec(SLIST_FIRST(pat), flags, m, e, NULL))
1808  return 1;
1809 
1810  if (up && (a = match_threadcomplete(pat, flags, m, t->parent, 1, 1, 1, 0)))
1811  return a;
1812  if (right && t->parent && (a = match_threadcomplete(pat, flags, m, t->next, 0, 0, 1, 1)))
1813  {
1814  return a;
1815  }
1816  if (left && t->parent && (a = match_threadcomplete(pat, flags, m, t->prev, 1, 0, 0, 1)))
1817  {
1818  return a;
1819  }
1820  if (down && (a = match_threadcomplete(pat, flags, m, t->child, 1, 0, 1, 1)))
1821  return a;
1822  return 0;
1823 }
struct MuttThread * next
Definition: thread.h:46
The envelope/body of an email.
Definition: email.h:37
static int match_threadcomplete(struct PatternHead *pat, PatternExecFlags flags, struct Mailbox *m, struct MuttThread *t, int left, int up, int right, int down)
Match a Pattern against an email thread.
Definition: pattern.c:1797
struct MuttThread * parent
Definition: thread.h:44
struct MuttThread * prev
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:1970
struct MuttThread * child
Definition: thread.h:45
#define SLIST_FIRST(head)
Definition: queue.h:229
struct Email * message
Definition: thread.h:48

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

1837 {
1838  if (!t || !t->parent || !t->parent->message)
1839  return 0;
1840 
1841  return mutt_pattern_exec(SLIST_FIRST(pat), flags, m, t->parent->message, NULL);
1842 }
struct MuttThread * parent
Definition: thread.h:44
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:1970
#define SLIST_FIRST(head)
Definition: queue.h:229
struct Email * message
Definition: thread.h:48

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

1856 {
1857  if (!t || !t->child)
1858  return 0;
1859 
1860  for (t = t->child; t; t = t->next)
1861  if (t->message && mutt_pattern_exec(SLIST_FIRST(pat), flags, m, t->message, NULL))
1862  return 1;
1863 
1864  return 0;
1865 }
struct MuttThread * next
Definition: thread.h:46
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:1970
struct MuttThread * child
Definition: thread.h:45
#define SLIST_FIRST(head)
Definition: queue.h:229
struct Email * message
Definition: thread.h:48

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

1875 {
1876  if (!b)
1877  return false;
1878 
1879  char buf[256];
1880  snprintf(buf, sizeof(buf), "%s/%s", TYPE(b), b->subtype);
1881 
1882  if (patmatch(pat, buf))
1883  return true;
1884  if (match_content_type(pat, b->parts))
1885  return true;
1886  if (match_content_type(pat, b->next))
1887  return true;
1888  return false;
1889 }
struct Body * next
next attachment in the list
Definition: body.h:60
char * subtype
content-type subtype
Definition: body.h:37
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:61
#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:1874
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:1065

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

1898 {
1899  struct Buffer *err = mutt_buffer_pool_get();
1900 
1901  bool rc = eval_date_minmax(pat, pat->p.str, err);
1903 
1904  return rc;
1905 }
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:577
union Pattern::@2 p
char * str
Definition: pattern.h:64
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:409
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:398

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

1917 {
1919  return match_content_type(pat, e->content);
1920 }
struct Body * content
list of MIME parts
Definition: email.h:93
void mutt_parse_mime_message(struct Mailbox *m, struct Email *e)
Parse a MIME email.
Definition: mutt_parse.c:50
static bool match_content_type(const struct Pattern *pat, struct Body *b)
Match a Pattern against an Attachment&#39;s Content-Type.
Definition: pattern.c:1874

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

1930 {
1931  *cache_entry = value ? 2 : 1;
1932 }

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

1941 {
1942  return cache_entry == 2;
1943 }

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

1951 {
1952  return cache_entry != 0;
1953 }

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

1972 {
1973  switch (pat->op)
1974  {
1975  case MUTT_PAT_AND:
1976  return pat->not^(perform_and(pat->child, flags, m, e, cache) > 0);
1977  case MUTT_PAT_OR:
1978  return pat->not^(perform_or(pat->child, flags, m, e, cache) > 0);
1979  case MUTT_PAT_THREAD:
1980  return pat->not^match_threadcomplete(pat->child, flags, m, e->thread, 1, 1, 1, 1);
1981  case MUTT_PAT_PARENT:
1982  return pat->not^match_threadparent(pat->child, flags, m, e->thread);
1983  case MUTT_PAT_CHILDREN:
1984  return pat->not^match_threadchildren(pat->child, flags, m, e->thread);
1985  case MUTT_ALL:
1986  return !pat->not;
1987  case MUTT_EXPIRED:
1988  return pat->not^e->expired;
1989  case MUTT_SUPERSEDED:
1990  return pat->not^e->superseded;
1991  case MUTT_FLAG:
1992  return pat->not^e->flagged;
1993  case MUTT_TAG:
1994  return pat->not^e->tagged;
1995  case MUTT_NEW:
1996  return pat->not? e->old || e->read : !(e->old || e->read);
1997  case MUTT_UNREAD:
1998  return pat->not? e->read : !e->read;
1999  case MUTT_REPLIED:
2000  return pat->not^e->replied;
2001  case MUTT_OLD:
2002  return pat->not? (!e->old || e->read) : (e->old && !e->read);
2003  case MUTT_READ:
2004  return pat->not^e->read;
2005  case MUTT_DELETED:
2006  return pat->not^e->deleted;
2007  case MUTT_PAT_MESSAGE:
2008  return pat->not^((EMSG(e) >= pat->min) && (EMSG(e) <= pat->max));
2009  case MUTT_PAT_DATE:
2010  if (pat->dynamic)
2012  return pat->not^(e->date_sent >= pat->min && e->date_sent <= pat->max);
2014  if (pat->dynamic)
2016  return pat->not^(e->received >= pat->min && e->received <= pat->max);
2017  case MUTT_PAT_BODY:
2018  case MUTT_PAT_HEADER:
2019  case MUTT_PAT_WHOLE_MSG:
2020  /* m can be NULL in certain cases, such as when replying to a message
2021  * from the attachment menu and the user has a reply-hook using "~e" (bug
2022  * #2190).
2023  * This is also the case when message scoring. */
2024  if (!m)
2025  return 0;
2026 #ifdef USE_IMAP
2027  /* IMAP search sets e->matched at search compile time */
2028  if ((m->magic == MUTT_IMAP) && pat->stringmatch)
2029  return e->matched;
2030 #endif
2031  return pat->not^msg_search(m, pat, e->msgno);
2032  case MUTT_PAT_SERVERSEARCH:
2033 #ifdef USE_IMAP
2034  if (!m)
2035  return 0;
2036  if (m->magic == MUTT_IMAP)
2037  {
2038  if (pat->stringmatch)
2039  return e->matched;
2040  return 0;
2041  }
2042  mutt_error(_("error: server custom search only supported with IMAP"));
2043  return 0;
2044 #else
2045  mutt_error(_("error: server custom search only supported with IMAP"));
2046  return -1;
2047 #endif
2048  case MUTT_PAT_SENDER:
2049  if (!e->env)
2050  return 0;
2051  return pat->not^match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1,
2052  e->env->sender);
2053  case MUTT_PAT_FROM:
2054  if (!e->env)
2055  return 0;
2056  return pat->not^match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1,
2057  e->env->from);
2058  case MUTT_PAT_TO:
2059  if (!e->env)
2060  return 0;
2061  return pat->not^match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1,
2062  e->env->to);
2063  case MUTT_PAT_CC:
2064  if (!e->env)
2065  return 0;
2066  return pat->not^match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 1,
2067  e->env->cc);
2068  case MUTT_PAT_SUBJECT:
2069  if (!e->env)
2070  return 0;
2071  return pat->not^(e->env->subject &&patmatch(pat, e->env->subject));
2072  case MUTT_PAT_ID:
2073  case MUTT_PAT_ID_EXTERNAL:
2074  if (!e->env)
2075  return 0;
2076  return pat->not^(e->env->message_id &&patmatch(pat, e->env->message_id));
2077  case MUTT_PAT_SCORE:
2078  return pat->not^(e->score >= pat->min &&
2079  (pat->max == MUTT_MAXRANGE || e->score <= pat->max));
2080  case MUTT_PAT_SIZE:
2081  return pat->not^(e->content->length >= pat->min &&
2082  (pat->max == MUTT_MAXRANGE || e->content->length <= pat->max));
2083  case MUTT_PAT_REFERENCE:
2084  if (!e->env)
2085  return 0;
2086  return pat->not^(match_reference(pat, &e->env->references) ||
2087  match_reference(pat, &e->env->in_reply_to));
2088  case MUTT_PAT_ADDRESS:
2089  if (!e->env)
2090  return 0;
2091  return pat->not^match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 4,
2092  e->env->from, e->env->sender, e->env->to,
2093  e->env->cc);
2094  case MUTT_PAT_RECIPIENT:
2095  if (!e->env)
2096  return 0;
2097  return pat->not^match_addrlist(pat, (flags & MUTT_MATCH_FULL_ADDRESS), 2,
2098  e->env->to, e->env->cc);
2099  case MUTT_PAT_LIST: /* known list, subscribed or not */
2100  {
2101  if (!e->env)
2102  return 0;
2103 
2104  int result;
2105  if (cache)
2106  {
2107  int *cache_entry = pat->alladdr ? &cache->list_all : &cache->list_one;
2108  if (!is_pattern_cache_set(*cache_entry))
2109  {
2111  cache_entry, mutt_is_list_cc(pat->alladdr, e->env->to, e->env->cc));
2112  }
2113  result = get_pattern_cache_value(*cache_entry);
2114  }
2115  else
2116  result = mutt_is_list_cc(pat->alladdr, e->env->to, e->env->cc);
2117  return pat->not^result;
2118  }
2120  {
2121  if (!e->env)
2122  return 0;
2123 
2124  int result;
2125  if (cache)
2126  {
2127  int *cache_entry = pat->alladdr ? &cache->sub_all : &cache->sub_one;
2128  if (!is_pattern_cache_set(*cache_entry))
2129  {
2131  cache_entry,
2132  mutt_is_list_recipient(pat->alladdr, e->env->to, e->env->cc));
2133  }
2134  result = get_pattern_cache_value(*cache_entry);
2135  }
2136  else
2137  result = mutt_is_list_recipient(pat->alladdr, e->env->to, e->env->cc);
2138  return pat->not^result;
2139  }
2141  {
2142  if (!e->env)
2143  return 0;
2144 
2145  int result;
2146  if (cache)
2147  {
2148  int *cache_entry = pat->alladdr ? &cache->pers_recip_all : &cache->pers_recip_one;
2149  if (!is_pattern_cache_set(*cache_entry))
2150  {
2151  set_pattern_cache_value(cache_entry,
2152  match_user(pat->alladdr, e->env->to, e->env->cc));
2153  }
2154  result = get_pattern_cache_value(*cache_entry);
2155  }
2156  else
2157  result = match_user(pat->alladdr, e->env->to, e->env->cc);
2158  return pat->not^result;
2159  }
2161  {
2162  if (!e->env)
2163  return 0;
2164 
2165  int result;
2166  if (cache)
2167  {
2168  int *cache_entry = pat->alladdr ? &cache->pers_from_all : &cache->pers_from_one;
2169  if (!is_pattern_cache_set(*cache_entry))
2170  set_pattern_cache_value(cache_entry, match_user(pat->alladdr, e->env->from, NULL));
2171  result = get_pattern_cache_value(*cache_entry);
2172  }
2173  else
2174  result = match_user(pat->alladdr, e->env->from, NULL);
2175  return pat->not^result;
2176  }
2177  case MUTT_PAT_COLLAPSED:
2178  return pat->not^(e->collapsed && e->num_hidden > 1);
2179  case MUTT_PAT_CRYPT_SIGN:
2180  if (!WithCrypto)
2181  break;
2182  return pat->not^((e->security & SEC_SIGN) ? 1 : 0);
2184  if (!WithCrypto)
2185  break;
2186  return pat->not^((e->security & SEC_GOODSIGN) ? 1 : 0);
2188  if (!WithCrypto)
2189  break;
2190  return pat->not^((e->security & SEC_ENCRYPT) ? 1 : 0);
2191  case MUTT_PAT_PGP_KEY:
2192  if (!(WithCrypto & APPLICATION_PGP))
2193  break;
2194  return pat->not^((e->security & PGP_KEY) == PGP_KEY);
2195  case MUTT_PAT_XLABEL:
2196  if (!e->env)
2197  return 0;
2198  return pat->not^(e->env->x_label &&patmatch(pat, e->env->x_label));
2199  case MUTT_PAT_DRIVER_TAGS:
2200  {
2201  char *tags = driver_tags_get(&e->tags);
2202  bool rc = (pat->not^(tags &&patmatch(pat, tags)));
2203  FREE(&tags);
2204  return rc;
2205  }
2206  case MUTT_PAT_HORMEL:
2207  if (!e->env)
2208  return 0;
2209  return pat->not^(e->env->spam && e->env->spam->data &&
2210  patmatch(pat, e->env->spam->data));
2211  case MUTT_PAT_DUPLICATED:
2212  return pat->not^(e->thread && e->thread->duplicate_thread);
2213  case MUTT_PAT_MIMEATTACH:
2214  if (!m)
2215  return 0;
2216  {
2217  int count = mutt_count_body_parts(m, e);
2218  return pat->not^(count >= pat->min &&
2219  (pat->max == MUTT_MAXRANGE || count <= pat->max));
2220  }
2221  case MUTT_PAT_MIMETYPE:
2222  if (!m)
2223  return 0;
2224  return pat->not^match_mime_content_type(pat, m, e);
2225  case MUTT_PAT_UNREFERENCED:
2226  return pat->not^(e->thread && !e->thread->child);
2227  case MUTT_PAT_BROKEN:
2228  return pat->not^(e->thread && e->thread->fake_thread);
2229 #ifdef USE_NNTP
2230  case MUTT_PAT_NEWSGROUPS:
2231  if (!e->env)
2232  return 0;
2233  return pat->not^(e->env->newsgroups &&patmatch(pat, e->env->newsgroups));
2234 #endif
2235  }
2236  mutt_error(_("error: unknown op %d (report this error)"), pat->op);
2237  return -1;
2238 }
Pattern matches date received.
Definition: pattern.h:114
Deleted messages.
Definition: mutt.h:104
Pattern matches email&#39;s header.
Definition: pattern.h:121
Pattern matches MIME type.
Definition: pattern.h:143
Pattern matches &#39;Date:&#39; field.
Definition: pattern.h:113
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:1797
static bool match_reference(struct Pattern *pat, struct ListHead *refs)
Match references against a Pattern.
Definition: pattern.c:1713
bool not
Definition: pattern.h:49
Pattern matches newsgroup.
Definition: pattern.h:145
Pattern matches email&#39;s score.
Definition: pattern.h:126
int pers_recip_all
^~p
Definition: pattern.h:88
struct Address * to
Definition: envelope.h:42
struct MuttThread * thread
Definition: email.h:97
static int match_addrlist(struct Pattern *pat, bool match_personal, int n,...)
Match a Pattern against and Address list.
Definition: pattern.c:1685
Message is part of a broken thread.
Definition: pattern.h:117
int mutt_is_list_recipient(bool alladdr, struct Address *a1, struct Address *a2)
Matches subscribed mailing lists.
Definition: pattern.c:1732
Pattern matches email&#39;s size.
Definition: pattern.h:127
struct Body * content
list of MIME parts
Definition: email.h:93
Flagged messages.
Definition: mutt.h:105
Pattern matches &#39;From:&#39; field.
Definition: pattern.h:112
#define MUTT_MAXRANGE
Definition: pattern.c:98
Email is from the user.
Definition: pattern.h:133
#define _(a)
Definition: message.h:28
Email is on mailing list.
Definition: pattern.h:130
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
struct TagHead tags
for drivers that support server tagging
Definition: email.h:110
Pattern matches a child email.
Definition: pattern.h:107
#define SEC_ENCRYPT
Email is encrypted.
Definition: ncrypt.h:120
bool expired
already expired?
Definition: email.h:52
Pattern matches email&#39;s Message-Id.
Definition: pattern.h:118
struct Address * sender
Definition: envelope.h:45
Messages that have been replied to.
Definition: mutt.h:98
int sub_all
^~u
Definition: pattern.h:86
Pattern matches message number.
Definition: pattern.h:125
Email is on subscribed mailing list.
Definition: pattern.h:131
static int is_pattern_cache_set(int cache_entry)
Is a given Pattern cached?
Definition: pattern.c:1950
All messages.
Definition: mutt.h:94
bool tagged
Definition: email.h:44
char * driver_tags_get(struct TagHead *head)
Get tags.
Definition: tags.c:150
bool read
Definition: email.h:51
bool dynamic
evaluate date ranges at run time
Definition: pattern.h:55
struct ListHead in_reply_to
in-reply-to header content
Definition: envelope.h:66
char * message_id
Definition: envelope.h:53
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:1835
bool old
Definition: email.h:50
#define SEC_GOODSIGN
Email has a valid signature.
Definition: ncrypt.h:122
enum MailboxType magic
mailbox type
Definition: mailbox.h:105
Duplicate message.
Definition: pattern.h:115
struct Envelope * env
envelope information
Definition: email.h:92
bool superseded
got superseded?
Definition: email.h:53
struct Address * from
Definition: envelope.h:41
int min
Definition: pattern.h:57
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:1641
int score
Definition: email.h:91
time_t date_sent
time when the message was sent (UTC)
Definition: email.h:84
Old messages.
Definition: mutt.h:97
int pers_from_one
~P
Definition: pattern.h:91
struct MuttThread * child
Definition: thread.h:45
bool duplicate_thread
Definition: thread.h:37
Server-side pattern matches.
Definition: pattern.h:140
Pattern matches &#39;Cc:&#39; field.
Definition: pattern.h:109
#define SEC_SIGN
Email is signed.
Definition: ncrypt.h:121
int pers_recip_one
~p
Definition: pattern.h:89
Message is unreferenced in the thread.
Definition: pattern.h:116
LOFF_T length
length (in bytes) of attachment
Definition: body.h:47
bool fake_thread
Definition: thread.h:36
Pattern matches keyword/label.
Definition: pattern.h:139
Either pattern can match.
Definition: pattern.h:104
size_t num_hidden
number of hidden messages in this view
Definition: email.h:78
#define PGP_KEY
Definition: ncrypt.h:138
Pattern matches email&#39;s spam score.
Definition: pattern.h:122
Superseded messages.
Definition: mutt.h:110
Tagged messages.
Definition: mutt.h:106
Message is encrypted.
Definition: pattern.h:137
char * data
pointer to data
Definition: buffer.h:35
int mutt_is_list_cc(int alladdr, struct Address *a1, struct Address *a2)
Matches known mailing lists.
Definition: pattern.c:1754
Pattern matches &#39;Subject:&#39; field.
Definition: pattern.h:111
int list_all
^~l
Definition: pattern.h:84
New messages.
Definition: mutt.h:96
Messages that have been read.
Definition: mutt.h:99
static int get_pattern_cache_value(int cache_entry)
Get pattern cache value.
Definition: pattern.c:1940
Email is addressed to the user.
Definition: pattern.h:132
Message has PGP key.
Definition: pattern.h:138
bool collapsed
is this message part of a collapsed thread?
Definition: email.h:76
short op
Definition: pattern.h:48
Pattern matches parent.
Definition: pattern.h:106
SecurityFlags security
bit 0-8: flags, bit 9,10: application.
Definition: email.h:39
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:72
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:1663
Expired messages.
Definition: mutt.h:109
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: ncrypt.h:129
int pers_from_all
^~P
Definition: pattern.h:90
Unread messages.
Definition: mutt.h:100
struct Buffer * spam
Definition: envelope.h:64
Pattern matches email&#39;s body.
Definition: pattern.h:120
static bool msg_search(struct Mailbox *m, struct Pattern *pat, int msgno)
Search an email.
Definition: pattern.c:1085
char * subject
Definition: envelope.h:50
bool flagged
marked important?
Definition: email.h:43
struct PatternHead * child
arguments to logical op
Definition: pattern.h:60
char * newsgroups
Definition: envelope.h:59
#define EMSG(e)
Definition: pattern.c:94
Message is signed.
Definition: pattern.h:135
bool deleted
Definition: email.h:45
#define mutt_error(...)
Definition: logging.h:83
bool replied
Definition: email.h:54
Thread is collapsed.
Definition: pattern.h:110
static int match_user(int alladdr, struct Address *a1, struct Address *a2)
Matches the user&#39;s email Address.
Definition: pattern.c:1773
Pattern matches sender.
Definition: pattern.h:124
Both patterns must match.
Definition: pattern.h:103
#define FREE(x)
Definition: memory.h:40
Message is crypographically verified.
Definition: pattern.h:136
int max
Definition: pattern.h:58
Pattern matches &#39;References:&#39; or &#39;In-Reply-To:&#39; field.
Definition: pattern.h:128
static bool match_update_dynamic_date(struct Pattern *pat)
Update a dynamic date pattern.
Definition: pattern.c:1897
bool stringmatch
Definition: pattern.h:51
Pattern matches message tags.
Definition: pattern.h:141
Pattern matches any address field.
Definition: pattern.h:134
User is a recipient of the email.
Definition: pattern.h:129
bool alladdr
Definition: pattern.h:50
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:1915
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:1854
Pattern matches email thread.
Definition: pattern.h:105
int mutt_count_body_parts(struct Mailbox *m, struct Email *e)
Count the MIME Body parts.
Definition: mutt_parse.c:216
Pattern matches &#39;To:&#39; field.
Definition: pattern.h:108
static void set_pattern_cache_value(int *cache_entry, int value)
Sets a value in the PatternCache cache entry.
Definition: pattern.c:1929
Pattern matches raw email text.
Definition: pattern.h:123
struct ListHead references
message references (in reverse order)
Definition: envelope.h:65
char * x_label
Definition: envelope.h:56
#define WithCrypto
Definition: ncrypt.h:155
Pattern matches number of attachments.
Definition: pattern.h:142
int list_one
~l
Definition: pattern.h:85
time_t received
time when the message was placed in the mailbox
Definition: email.h:85
Message-Id is among results from an external query.
Definition: pattern.h:119
static bool patmatch(const struct Pattern *pat, const char *buf)
Compare a string to a Pattern.
Definition: pattern.c:1065
struct Address * cc
Definition: envelope.h:43
bool matched
Definition: email.h:70
int msgno
number displayed to the user
Definition: email.h:89
int sub_one
~u
Definition: pattern.h:87

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

2246 {
2247  mutt_buffer_reset(buf);
2248  mutt_buffer_addch(buf, '"');
2249  while (*str)
2250  {
2251  if ((*str == '\\') || (*str == '"'))
2252  mutt_buffer_addch(buf, '\\');
2253  mutt_buffer_addch(buf, *str++);
2254  }
2255  mutt_buffer_addch(buf, '"');
2256 }
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:83
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:279

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

2264 {
2265  bool do_simple = true;
2266 
2267  for (const char *p = mutt_b2s(buf); p && *p; p++)
2268  {
2269  if ((*p == '\\') && *(p + 1))
2270  p++;
2271  else if ((*p == '~') || (*p == '=') || (*p == '%'))
2272  {
2273  do_simple = false;
2274  break;
2275  }
2276  }
2277 
2278  /* XXX - is mutt_str_strcasecmp() right here, or should we use locale's
2279  * equivalences? */
2280 
2281  if (do_simple) /* yup, so spoof a real request */
2282  {
2283  /* convert old tokens into the new format */
2284  if ((mutt_str_strcasecmp("all", mutt_b2s(buf)) == 0) ||
2285  (mutt_str_strcmp("^", mutt_b2s(buf)) == 0) ||
2286  (mutt_str_strcmp(".", mutt_b2s(buf)) == 0)) /* ~A is more efficient */
2287  {
2288  mutt_buffer_strcpy(buf, "~A");
2289  }
2290  else if (mutt_str_strcasecmp("del", mutt_b2s(buf)) == 0)
2291  mutt_buffer_strcpy(buf, "~D");
2292  else if (mutt_str_strcasecmp("flag", mutt_b2s(buf)) == 0)
2293  mutt_buffer_strcpy(buf, "~F");
2294  else if (mutt_str_strcasecmp("new", mutt_b2s(buf)) == 0)
2295  mutt_buffer_strcpy(buf, "~N");
2296  else if (mutt_str_strcasecmp("old", mutt_b2s(buf)) == 0)
2297  mutt_buffer_strcpy(buf, "~O");
2298  else if (mutt_str_strcasecmp("repl", mutt_b2s(buf)) == 0)
2299  mutt_buffer_strcpy(buf, "~Q");
2300  else if (mutt_str_strcasecmp("read", mutt_b2s(buf)) == 0)
2301  mutt_buffer_strcpy(buf, "~R");
2302  else if (mutt_str_strcasecmp("tag", mutt_b2s(buf)) == 0)
2303  mutt_buffer_strcpy(buf, "~T");
2304  else if (mutt_str_strcasecmp("unread", mutt_b2s(buf)) == 0)
2305  mutt_buffer_strcpy(buf, "~U");
2306  else
2307  {
2308  struct Buffer *tmp = mutt_buffer_pool_get();
2309  quote_simple(mutt_b2s(buf), tmp);
2310  mutt_file_expand_fmt(buf, simple, mutt_b2s(tmp));
2312  }
2313  }
2314 }
static void quote_simple(const char *str, struct Buffer *buf)
Apply simple quoting to a string.
Definition: pattern.c:2245
String manipulation buffer.
Definition: buffer.h:33
#define mutt_b2s(buf)
Definition: buffer.h:42
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:322
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:1408
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:631
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:409
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:618
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:398

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

2323 {
2324  if (!e)
2325  return NULL;
2326 
2327  struct MuttThread *t = e->thread;
2328 
2329  while (t && t->parent)
2330  t = t->parent;
2331 
2332  return t;
2333 }
struct MuttThread * thread
Definition: email.h:97
struct MuttThread * parent
Definition: thread.h:44
An email conversation.
Definition: thread.h:34

+ Here is the caller graph for this function:

bool mutt_limit_current_thread ( struct Email e)

Limit the email view to the current thread.

Parameters
eCurrent Email
Return values
trueSuccess
falseFailure

Definition at line 2341 of file pattern.c.

2342 {
2343  if (!e)
2344  return false;
2345 
2346  struct MuttThread *me = top_of_thread(e);
2347  if (!me)
2348  return false;
2349 
2350  Context->mailbox->vcount = 0;
2351  Context->vsize = 0;
2352  Context->collapsed = false;
2353 
2354  for (int i = 0; i < Context->mailbox->msg_count; i++)
2355  {
2356  Context->mailbox->emails[i]->virtual = -1;
2357  Context->mailbox->emails[i]->limited = false;
2358  Context->mailbox->emails[i]->collapsed = false;
2359  Context->mailbox->emails[i]->num_hidden = 0;
2360 
2361  if (top_of_thread(Context->mailbox->emails[i]) == me)
2362  {
2363  struct Body *body = Context->mailbox->emails[i]->content;
2364 
2366  Context->mailbox->emails[i]->limited = true;
2368  Context->mailbox->vcount++;
2369  Context->vsize += (body->length + body->offset - body->hdr_offset);
2370  }
2371  }
2372  return true;
2373 }
struct Email ** emails
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:38
int msg_count
total number of messages
Definition: mailbox.h:92
int virtual
virtual message number
Definition: email.h:90
struct Body * content
list of MIME parts
Definition: email.h:93
LOFF_T offset
offset where the actual data begins
Definition: body.h:46
int vcount
the number of virtual messages
Definition: mailbox.h:102
The body of an email.
Definition: body.h:34
struct Mailbox * mailbox
Definition: context.h:52
bool limited
is this message in a limited view?
Definition: email.h:77
off_t vsize
Definition: context.h:40
LOFF_T length
length (in bytes) of attachment
Definition: body.h:47
static struct MuttThread * top_of_thread(struct Email *e)
Find the first email in the current thread.
Definition: pattern.c:2322
size_t num_hidden
number of hidden messages in this view
Definition: email.h:78
bool collapsed
is this message part of a collapsed thread?
Definition: email.h:76
An email conversation.
Definition: thread.h:34
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:101
bool collapsed
are all threads collapsed?
Definition: context.h:50
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 2382 of file pattern.c.

2383 {
2384  struct Buffer err;
2385  int rc = -1;
2386  struct Progress progress;
2387  struct Buffer *buf = mutt_buffer_pool_get();
2388 
2390  if (prompt || (op != MUTT_LIMIT))
2391  {
2392  if ((mutt_get_field(prompt, buf->data, buf->dsize, MUTT_PATTERN | MUTT_CLEAR) != 0) ||
2393  !(mutt_b2s(buf)[0]))
2394  {
2396  return -1;
2397  }
2398  }
2399  mutt_buffer_fix_dptr(buf);
2400 
2401  mutt_message(_("Compiling search pattern..."));
2402 
2403  char *simple = mutt_str_strdup(mutt_b2s(buf));
2405 
2406  mutt_buffer_init(&err);
2407  err.dsize = 256;
2408  err.data = mutt_mem_malloc(err.dsize);
2409  struct PatternHead *pat = mutt_pattern_comp(buf->data, MUTT_FULL_MSG, &err);
2410  if (!pat)
2411  {
2412  mutt_error("%s", err.data);
2413  goto bail;
2414  }
2415 
2416 #ifdef USE_IMAP
2417  if ((Context->mailbox->magic == MUTT_IMAP) && (imap_search(Context->mailbox, pat) < 0))
2418  goto bail;
2419 #endif
2420 
2421  mutt_progress_init(&progress, _("Executing command on matching messages..."),
2423  (op == MUTT_LIMIT) ? Context->mailbox->msg_count :
2424  Context->mailbox->vcount);
2425 
2426  if (op == MUTT_LIMIT)
2427  {
2428  Context->mailbox->vcount = 0;
2429  Context->vsize = 0;
2430  Context->collapsed = false;
2431  int padding = mx_msg_padding_size(Context->mailbox);
2432 
2433  for (int i = 0; i < Context->mailbox->msg_count; i++)
2434  {
2435  mutt_progress_update(&progress, i, -1);
2436  /* new limit pattern implicitly uncollapses all threads */
2437  Context->mailbox->emails[i]->virtual = -1;
2438  Context->mailbox->emails[i]->limited = false;
2439  Context->mailbox->emails[i]->collapsed = false;
2440  Context->mailbox->emails[i]->num_hidden = 0;
2442  Context->mailbox, Context->mailbox->emails[i], NULL))
2443  {
2445  Context->mailbox->emails[i]->limited = true;
2447  Context->mailbox->vcount++;
2448  struct Body *b = Context->mailbox->emails[i]->content;
2449  Context->vsize += b->length + b->offset - b->hdr_offset + padding;
2450  }
2451  }
2452  }
2453  else
2454  {
2455  for (int i = 0; i < Context->mailbox->vcount; i++)
2456  {
2457  mutt_progress_update(&progress, i, -1);
2459  Context->mailbox->emails[Context->mailbox->v2r[i]], NULL))
2460  {
2461  switch (op)
2462  {
2463  case MUTT_UNDELETE:
2466  MUTT_PURGE, false);
2467  /* fallthrough */
2468  case MUTT_DELETE:
2471  MUTT_DELETE, (op == MUTT_DELETE));
2472  break;
2473  case MUTT_TAG:
2474  case MUTT_UNTAG:
2477  MUTT_TAG, (op == MUTT_TAG));
2478  break;
2479  }
2480  }
2481  }
2482  }
2483 
2484  mutt_clear_error();
2485 
2486  if (op == MUTT_LIMIT)
2487  {
2488  /* drop previous limit pattern */
2489  FREE(&Context->pattern);
2491 
2493  mutt_error(_("No messages matched criteria"));
2494 
2495  /* record new limit pattern, unless match all */
2496  const char *pbuf = mutt_b2s(buf);
2497  while (*pbuf == ' ')
2498  pbuf++;
2499  if (mutt_str_strcmp(pbuf, "~A") != 0)
2500  {
2501  Context->pattern = simple;
2502  simple = NULL; /* don't clobber it */
2504  }
2505  }
2506 
2507  rc = 0;
2508 
2509 bail:
2511  FREE(&simple);
2512  mutt_pattern_free(&pat);
2513  FREE(&err.data);
2514 
2515  return rc;
2516 }
struct Email ** emails
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:38
#define MUTT_PROGRESS_MSG
message-based progress
Definition: progress.h:33
#define NONULL(x)
Definition: string2.h:36
int msg_count
total number of messages
Definition: mailbox.h:92
#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:67
#define mutt_message(...)
Definition: logging.h:82
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:2263
int virtual
virtual message number
Definition: email.h:90
Messages in limited view.
Definition: mutt.h:108
struct Body * content
list of MIME parts
Definition: email.h:93
#define MUTT_FULL_MSG
enable body and header matching
Definition: pattern.h:40
void mutt_progress_update(struct Progress *progress, long pos, int percent)
Update the state of the progress bar.
Definition: progress.c:171
void mutt_progress_init(struct Progress *progress, const char *msg, unsigned short flags, unsigned short inc, size_t size)
Set up a progress bar.
Definition: progress.c:114
String manipulation buffer.
Definition: buffer.h:33
Messages to be un-deleted.
Definition: mutt.h:102
LOFF_T offset
offset where the actual data begins
Definition: body.h:46
int imap_search(struct Mailbox *m, const struct PatternHead *pat)
Find a matching mailbox.
Definition: imap.c:1355
#define _(a)
Definition: message.h:28
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
Messages to be purged (bypass trash)
Definition: mutt.h:103
A progress bar.
Definition: progress.h:38
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:69
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
int vcount
the number of virtual messages
Definition: mailbox.h:102
The body of an email.
Definition: body.h:34
struct PatternHead * limit_pattern
compiled limit pattern
Definition: context.h:42
size_t dsize
length of data
Definition: buffer.h:37
struct Mailbox * mailbox
Definition: context.h:52
enum MailboxType magic
mailbox type
Definition: mailbox.h:105
bool limited
is this message in a limited view?
Definition: email.h:77
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:221
off_t vsize
Definition: context.h:40
#define mutt_b2s(buf)
Definition: buffer.h:42
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1970
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:322
#define SLIST_FIRST(head)
Definition: queue.h:229
LOFF_T length
length (in bytes) of attachment
Definition: body.h:47
Messages to be deleted.
Definition: mutt.h:101
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:97
size_t num_hidden
number of hidden messages in this view
Definition: email.h:78
Tagged messages.
Definition: mutt.h:106
char * data
pointer to data
Definition: buffer.h:35
struct PatternHead * mutt_pattern_comp(char *s, int flags, struct Buffer *err)
Create a Pattern.
Definition: pattern.c:1388
bool collapsed
is this message part of a collapsed thread?
Definition: email.h:76
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:72
WHERE char * C_SimpleSearch
Config: Pattern to search for when search doesn&#39;t contain ~&#39;s.
Definition: globals.h:138
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:101
char * mutt_str_strdup(const char *str)
Copy a string, safely.
Definition: string.c:380
bool collapsed
are all threads collapsed?
Definition: context.h:50
#define mutt_error(...)
Definition: logging.h:83
#define FREE(x)
Definition: memory.h:40
Messages to be un-tagged.
Definition: mutt.h:107
int mx_msg_padding_size(struct Mailbox *m)
Bytes of padding between messages - Wrapper for MxOps::msg_padding_size.
Definition: mx.c:1454
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:68
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:409
char * pattern
limit pattern string
Definition: context.h:41
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:618
WHERE short C_ReadInc
Config: Update the progress bar after this many records read (0 to disable)
Definition: globals.h:148
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:398
void mutt_pattern_free(struct PatternHead **pat)
Free a Pattern.
Definition: pattern.c:1336

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

2526 {
2527  struct Progress progress;
2528 
2529  if (!*LastSearch || ((op != OP_SEARCH_NEXT) && (op != OP_SEARCH_OPPOSITE)))
2530  {
2531  char buf[256];
2532  mutt_str_strfcpy(buf, *LastSearch ? LastSearch : "", sizeof(buf));
2533  if ((mutt_get_field(((op == OP_SEARCH) || (op == OP_SEARCH_NEXT)) ?
2534  _("Search for: ") :
2535  _("Reverse search for: "),
2536  buf, sizeof(buf), MUTT_CLEAR | MUTT_PATTERN) != 0) ||
2537  !buf[0])
2538  {
2539  return -1;
2540  }
2541 
2542  if ((op == OP_SEARCH) || (op == OP_SEARCH_NEXT))
2543  OptSearchReverse = false;
2544  else
2545  OptSearchReverse = true;
2546 
2547  /* compare the *expanded* version of the search pattern in case
2548  * $simple_search has changed while we were searching */
2549  struct Buffer *tmp = mutt_buffer_pool_get();
2550  mutt_buffer_strcpy(tmp, buf);
2552 
2553  if (!SearchPattern || (mutt_str_strcmp(mutt_b2s(tmp), LastSearchExpn) != 0))
2554  {
2555  struct Buffer err;
2556  mutt_buffer_init(&err);
2557  OptSearchInvalid = true;
2558  mutt_str_strfcpy(LastSearch, buf, sizeof(LastSearch));
2560  mutt_message(_("Compiling search pattern..."));
2562  err.dsize = 256;
2563  err.data = mutt_mem_malloc(err.dsize);
2565  if (!SearchPattern)
2566  {
2568  mutt_error("%s", err.data);
2569  FREE(&err.data);
2570  LastSearch[0] = '\0';
2571  LastSearchExpn[0] = '\0';
2572  return -1;
2573  }
2574  FREE(&err.data);
2575  mutt_clear_error();
2576  }
2577 
2579  }
2580 
2581  if (OptSearchInvalid)
2582  {
2583  for (int i = 0; i < Context->mailbox->msg_count; i++)
2584  Context->mailbox->emails[i]->searched = false;
2585 #ifdef USE_IMAP
2586  if ((Context->mailbox->magic == MUTT_IMAP) &&
2588  return -1;
2589 #endif
2590  OptSearchInvalid = false;
2591  }
2592 
2593  int incr = OptSearchReverse ? -1 : 1;
2594  if (op == OP_SEARCH_OPPOSITE)
2595  incr = -incr;
2596 
2597  mutt_progress_init(&progress, _("Searching..."), MUTT_PROGRESS_MSG, C_ReadInc,
2598  Context->mailbox->vcount);
2599 
2600  for (int i = cur + incr, j = 0; j != Context->mailbox->vcount; j++)
2601  {
2602  const char *msg = NULL;
2603  mutt_progress_update(&progress, j, -1);
2604  if (i > Context->mailbox->vcount - 1)
2605  {
2606  i = 0;
2607  if (C_WrapSearch)
2608  msg = _("Search wrapped to top");
2609  else
2610  {
2611  mutt_message(_("Search hit bottom without finding match"));
2612  return -1;
2613  }
2614  }
2615  else if (i < 0)
2616  {
2617  i = Context->mailbox->vcount - 1;
2618  if (C_WrapSearch)
2619  msg = _("Search wrapped to bottom");
2620  else
2621  {
2622  mutt_message(_("Search hit top without finding match"));
2623  return -1;
2624  }
2625  }
2626 
2627  struct Email *e = Context->mailbox->emails[Context->mailbox->v2r[i]];
2628  if (e->searched)
2629  {
2630  /* if we've already evaluated this message, use the cached value */
2631  if (e->matched)
2632  {
2633  mutt_clear_error();
2634  if (msg && *msg)
2635  mutt_message(msg);
2636  return i;
2637  }
2638  }
2639  else
2640  {
2641  /* remember that we've already searched this message */
2642  e->searched = true;
2644  Context->mailbox, e, NULL);
2645  if (e->matched > 0)
2646  {
2647  mutt_clear_error();
2648  if (msg && *msg)
2649  mutt_message(msg);
2650  return i;
2651  }
2652  }
2653 
2654  if (SigInt)
2655  {
2656  mutt_error(_("Search interrupted"));
2657  SigInt = 0;
2658  return -1;
2659  }
2660 
2661  i += incr;
2662  }
2663 
2664  mutt_error(_("Not found"));
2665  return -1;
2666 }
struct Email ** emails
Definition: mailbox.h:99
The "current" mailbox.
Definition: context.h:38
#define MUTT_PROGRESS_MSG
message-based progress
Definition: progress.h:33
#define NONULL(x)
Definition: string2.h:36
int msg_count
total number of messages
Definition: mailbox.h:92
The envelope/body of an email.
Definition: email.h:37
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:67
#define mutt_message(...)
Definition: logging.h:82
void mutt_check_simple(struct Buffer *buf, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:2263
WHERE SIG_ATOMIC_VOLATILE_T SigInt
true after SIGINT is received
Definition: globals.h:83
#define MUTT_FULL_MSG
enable body and header matching
Definition: pattern.h:40
void mutt_progress_update(struct Progress *progress, long pos, int percent)
Update the state of the progress bar.
Definition: progress.c:171
void mutt_progress_init(struct Progress *progress, const char *msg, unsigned short flags, unsigned short inc, size_t size)
Set up a progress bar.
Definition: progress.c:114
String manipulation buffer.
Definition: buffer.h:33
int imap_search(struct Mailbox *m, const struct PatternHead *pat)
Find a matching mailbox.
Definition: imap.c:1355
#define _(a)
Definition: message.h:28
static char LastSearch[256]
last pattern searched for
Definition: pattern.c:201
WHERE bool C_WrapSearch
Config: Wrap around when the search hits the end.
Definition: globals.h:259
&#39;IMAP&#39; Mailbox type
Definition: magic.h:42
bool searched
Definition: email.h:69
A progress bar.
Definition: progress.h:38
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:69
#define mutt_get_field(field, buf, buflen, complete)
Definition: curs_lib.h:86
int vcount
the number of virtual messages
Definition: mailbox.h:102
struct Mailbox * mailbox
Definition: context.h:52
enum MailboxType magic
mailbox type
Definition: mailbox.h:105
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:141
#define mutt_b2s(buf)
Definition: buffer.h:42
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: pattern.c:1970
void mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:322
static char LastSearchExpn[1024]
expanded version of LastSearch
Definition: pattern.c:202
#define SLIST_FIRST(head)
Definition: queue.h:229
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:97
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:753
struct PatternHead * mutt_pattern_comp(char *s, int flags, struct Buffer *err)
Create a Pattern.
Definition: pattern.c:1388
WHERE bool OptSearchInvalid
(pseudo) used to invalidate the search pat
Definition: options.h:49
#define MUTT_MATCH_FULL_ADDRESS
Match the full address.
Definition: pattern.h:72
WHERE char * C_SimpleSearch
Config: Pattern to search for when search doesn&#39;t contain ~&#39;s.
Definition: globals.h:138
int * v2r
mapping from virtual to real msgno
Definition: mailbox.h:101
static struct PatternHead * SearchPattern
current search pattern
Definition: pattern.c:200
#define mutt_error(...)
Definition: logging.h:83
#define FREE(x)
Definition: memory.h:40
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:68
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: buffer.c:409
int mutt_str_strcmp(const char *a, const char *b)
Compare two strings, safely.
Definition: string.c:618
WHERE bool OptSearchReverse
(pseudo) used by ci_search_command
Definition: options.h:50
WHERE short C_ReadInc
Config: Update the progress bar after this many records read (0 to disable)
Definition: globals.h:148
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: buffer.c:398
bool matched
Definition: email.h:70
void mutt_pattern_free(struct PatternHead **pat)
Free a Pattern.
Definition: pattern.c:1336

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

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

Set of Regexes for various range types.

This array, will also contain the compiled regexes.

Definition at line 191 of file pattern.c.

struct PatternHead* SearchPattern = NULL
static

current search pattern

Definition at line 200 of file pattern.c.

char LastSearch[256] = { 0 }
static

last pattern searched for

Definition at line 201 of file pattern.c.

char LastSearchExpn[1024] = { 0 }
static

expanded version of LastSearch

Definition at line 202 of file pattern.c.

const struct PatternFlags Flags[]
static

Lookup table for all patterns.

Definition at line 1240 of file pattern.c.