NeoMutt  2020-06-26-250-g349c94
Teaching an old dog new tricks
DOXYGEN
search.c File Reference

IMAP search routines. More...

#include "config.h"
#include <stdbool.h>
#include <string.h>
#include "private.h"
#include "mutt/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "lib.h"
#include "pattern/lib.h"
+ Include dependency graph for search.c:

Go to the source code of this file.

Functions

static int check_pattern_list (const struct PatternList *patterns)
 Check how many patterns in a list can be searched server-side. More...
 
static bool compile_search (const struct ImapAccountData *adata, const struct Pattern *pat, struct Buffer *buf)
 Convert NeoMutt pattern to IMAP search. More...
 
static bool check_pattern (const struct Pattern *pat)
 Check whether a pattern can be searched server-side. More...
 
static bool compile_search_children (const struct ImapAccountData *adata, const struct Pattern *pat, struct Buffer *buf)
 Compile a search command for a pattern's children. More...
 
static bool compile_search_self (const struct ImapAccountData *adata, const struct Pattern *pat, struct Buffer *buf)
 Compile a search command for a pattern. More...
 
bool imap_search (struct Mailbox *m, const struct PatternList *pat)
 Find messages in mailbox matching a pattern. More...
 
void cmd_parse_search (struct ImapAccountData *adata, const char *s)
 store SEARCH response for later use More...
 

Detailed Description

IMAP search routines.

Authors
  • Michael R. Elkins
  • Brandon Long
  • Brendan Cully
  • Richard Russon

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 search.c.

Function Documentation

◆ check_pattern_list()

static int check_pattern_list ( const struct PatternList *  patterns)
static

Check how many patterns in a list can be searched server-side.

Parameters
patternsList of patterns to match
Return values
numNumber of patterns search that can be searched server-side

Definition at line 82 of file search.c.

83 {
84  int positives = 0;
85 
86  const struct Pattern *pat = NULL;
87  SLIST_FOREACH(pat, patterns, entries)
88  {
89  positives += check_pattern(pat);
90  }
91 
92  return positives;
93 }
static bool check_pattern(const struct Pattern *pat)
Check whether a pattern can be searched server-side.
Definition: search.c:56
A simple (non-regex) pattern.
Definition: lib.h:65
#define SLIST_FOREACH(var, head, field)
Definition: queue.h:230
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compile_search()

static bool compile_search ( const struct ImapAccountData adata,
const struct Pattern pat,
struct Buffer buf 
)
static

Convert NeoMutt pattern to IMAP search.

Parameters
adataImap Account data
patPattern to convert
bufBuffer for result
Return values
Trueon success
Falseon failure

Convert neomutt Pattern to IMAP SEARCH command containing only elements that require full-text search (neomutt already has what it needs for most match types, and does a better job (eg server doesn't support regexes).

Definition at line 208 of file search.c.

210 {
211  if (!check_pattern(pat))
212  return true;
213 
214  if (pat->pat_not)
215  mutt_buffer_addstr(buf, "NOT ");
216 
217  return pat->child ? compile_search_children(adata, pat, buf) :
218  compile_search_self(adata, pat, buf);
219 }
struct PatternList * child
Arguments to logical operation.
Definition: lib.h:79
static bool check_pattern(const struct Pattern *pat)
Check whether a pattern can be searched server-side.
Definition: search.c:56
static bool compile_search_children(const struct ImapAccountData *adata, const struct Pattern *pat, struct Buffer *buf)
Compile a search command for a pattern&#39;s children.
Definition: search.c:103
bool pat_not
Pattern should be inverted (not)
Definition: lib.h:68
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
static bool compile_search_self(const struct ImapAccountData *adata, const struct Pattern *pat, struct Buffer *buf)
Compile a search command for a pattern.
Definition: search.c:142
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ check_pattern()

static bool check_pattern ( const struct Pattern pat)
static

Check whether a pattern can be searched server-side.

Parameters
patPattern to check
Return values
truePattern can be searched server-side
falsePattern cannot be searched server-side

Definition at line 56 of file search.c.

57 {
58  switch (pat->op)
59  {
60  case MUTT_PAT_BODY:
61  case MUTT_PAT_HEADER:
62  case MUTT_PAT_WHOLE_MSG:
63  if (pat->string_match)
64  return true;
65  break;
67  return true;
68  break;
69  default:
70  if (pat->child && check_pattern_list(pat->child))
71  return true;
72  break;
73  }
74  return false;
75 }
struct PatternList * child
Arguments to logical operation.
Definition: lib.h:79
Pattern matches email&#39;s body.
Definition: lib.h:140
Pattern matches email&#39;s header.
Definition: lib.h:141
Server-side pattern matches.
Definition: lib.h:160
bool string_match
Check a string for a match.
Definition: lib.h:70
static int check_pattern_list(const struct PatternList *patterns)
Check how many patterns in a list can be searched server-side.
Definition: search.c:82
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: lib.h:67
Pattern matches raw email text.
Definition: lib.h:143
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compile_search_children()

static bool compile_search_children ( const struct ImapAccountData adata,
const struct Pattern pat,
struct Buffer buf 
)
static

Compile a search command for a pattern's children.

Parameters
adataImap Account data
patParent pattern
bufBuffer for the resulting command
Return values
Trueon success
Falseon failure

Definition at line 103 of file search.c.

105 {
106  int clauses = check_pattern_list(pat->child);
107  if (clauses == 0)
108  return true;
109 
110  mutt_buffer_addch(buf, '(');
111 
112  struct Pattern *c;
113  SLIST_FOREACH(c, pat->child, entries)
114  {
115  if (!check_pattern(c))
116  continue;
117 
118  if ((pat->op == MUTT_PAT_OR) && (clauses > 1))
119  mutt_buffer_addstr(buf, "OR ");
120 
121  if (!compile_search(adata, c, buf))
122  return false;
123 
124  if (clauses > 1)
125  mutt_buffer_addch(buf, ' ');
126 
127  clauses--;
128  }
129 
130  mutt_buffer_addch(buf, ')');
131  return true;
132 }
struct PatternList * child
Arguments to logical operation.
Definition: lib.h:79
static bool check_pattern(const struct Pattern *pat)
Check whether a pattern can be searched server-side.
Definition: search.c:56
static bool compile_search(const struct ImapAccountData *adata, const struct Pattern *pat, struct Buffer *buf)
Convert NeoMutt pattern to IMAP search.
Definition: search.c:208
A simple (non-regex) pattern.
Definition: lib.h:65
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
static int check_pattern_list(const struct PatternList *patterns)
Check how many patterns in a list can be searched server-side.
Definition: search.c:82
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: lib.h:67
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
Either pattern can match.
Definition: lib.h:124
#define SLIST_FOREACH(var, head, field)
Definition: queue.h:230
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compile_search_self()

static bool compile_search_self ( const struct ImapAccountData adata,
const struct Pattern pat,
struct Buffer buf 
)
static

Compile a search command for a pattern.

Parameters
adataImap Account data
patPattern
bufBuffer for the resulting command
Return values
Trueon success
Falseon failure

Definition at line 142 of file search.c.

144 {
145  char term[256];
146  char *delim = NULL;
147 
148  switch (pat->op)
149  {
150  case MUTT_PAT_HEADER:
151  mutt_buffer_addstr(buf, "HEADER ");
152 
153  /* extract header name */
154  delim = strchr(pat->p.str, ':');
155  if (!delim)
156  {
157  mutt_error(_("Header search without header name: %s"), pat->p.str);
158  return false;
159  }
160  *delim = '\0';
161  imap_quote_string(term, sizeof(term), pat->p.str, false);
162  mutt_buffer_addstr(buf, term);
163  mutt_buffer_addch(buf, ' ');
164 
165  /* and field */
166  *delim = ':';
167  delim++;
168  SKIPWS(delim);
169  imap_quote_string(term, sizeof(term), delim, false);
170  mutt_buffer_addstr(buf, term);
171  break;
172  case MUTT_PAT_BODY:
173  mutt_buffer_addstr(buf, "BODY ");
174  imap_quote_string(term, sizeof(term), pat->p.str, false);
175  mutt_buffer_addstr(buf, term);
176  break;
177  case MUTT_PAT_WHOLE_MSG:
178  mutt_buffer_addstr(buf, "TEXT ");
179  imap_quote_string(term, sizeof(term), pat->p.str, false);
180  mutt_buffer_addstr(buf, term);
181  break;
183  if (!(adata->capabilities & IMAP_CAP_X_GM_EXT_1))
184  {
185  mutt_error(_("Server-side custom search not supported: %s"), pat->p.str);
186  return false;
187  }
188  mutt_buffer_addstr(buf, "X-GM-RAW ");
189  imap_quote_string(term, sizeof(term), pat->p.str, false);
190  mutt_buffer_addstr(buf, term);
191  break;
192  }
193  return true;
194 }
Pattern matches email&#39;s body.
Definition: lib.h:140
#define _(a)
Definition: message.h:28
Pattern matches email&#39;s header.
Definition: lib.h:141
Server-side pattern matches.
Definition: lib.h:160
#define SKIPWS(ch)
Definition: string2.h:46
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
union Pattern::@1 p
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: lib.h:67
ImapCapFlags capabilities
Definition: private.h:185
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:240
char * str
String, if string_match is set.
Definition: lib.h:83
#define mutt_error(...)
Definition: logging.h:84
Pattern matches raw email text.
Definition: lib.h:143
#define IMAP_CAP_X_GM_EXT_1
https://developers.google.com/gmail/imap/imap-extensions
Definition: private.h:140
void imap_quote_string(char *dest, size_t dlen, const char *src, bool quote_backtick)
quote string according to IMAP rules
Definition: util.c:971
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_search()

bool imap_search ( struct Mailbox m,
const struct PatternList *  pat 
)

Find messages in mailbox matching a pattern.

Parameters
mMailbox
patPattern to match
Return values
trueSuccess
falseFailure

Definition at line 228 of file search.c.

229 {
230  for (int i = 0; i < m->msg_count; i++)
231  {
232  struct Email *e = m->emails[i];
233  if (!e)
234  break;
235  e->matched = false;
236  }
237 
238  if (check_pattern_list(pat) == 0)
239  return true;
240 
241  struct Buffer buf;
242  mutt_buffer_init(&buf);
243  mutt_buffer_addstr(&buf, "UID SEARCH ");
244 
245  struct ImapAccountData *adata = imap_adata_get(m);
246  const bool ok = compile_search(adata, SLIST_FIRST(pat), &buf) &&
248 
249  FREE(&buf.data);
250  return ok;
251 }
struct Email ** emails
Array of Emails.
Definition: mailbox.h:99
int msg_count
Total number of messages.
Definition: mailbox.h:91
The envelope/body of an email.
Definition: email.h:37
static bool compile_search(const struct ImapAccountData *adata, const struct Pattern *pat, struct Buffer *buf)
Convert NeoMutt pattern to IMAP search.
Definition: search.c:208
String manipulation buffer.
Definition: buffer.h:33
Imap command executed or queued successfully.
Definition: private.h:83
int imap_exec(struct ImapAccountData *adata, const char *cmdstr, ImapCmdFlags flags)
Execute a command and wait for the response from the server.
Definition: command.c:1247
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
static int check_pattern_list(const struct PatternList *patterns)
Check how many patterns in a list can be searched server-side.
Definition: search.c:82
#define SLIST_FIRST(head)
Definition: queue.h:228
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:72
IMAP-specific Account data -.
Definition: private.h:169
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: util.c:113
char * buf
Definition: private.h:189
#define FREE(x)
Definition: memory.h:40
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
bool matched
Search matches this Email.
Definition: email.h:68
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ cmd_parse_search()

void cmd_parse_search ( struct ImapAccountData adata,
const char *  s 
)

store SEARCH response for later use

Parameters
adataImap Account data
sCommand string with search results

Definition at line 258 of file search.c.

259 {
260  unsigned int uid;
261  struct Email *e = NULL;
262  struct ImapMboxData *mdata = adata->mailbox->mdata;
263 
264  mutt_debug(LL_DEBUG2, "Handling SEARCH\n");
265 
266  while ((s = imap_next_word((char *) s)) && (*s != '\0'))
267  {
268  if (mutt_str_atoui(s, &uid) < 0)
269  continue;
270  e = mutt_hash_int_find(mdata->uid_hash, uid);
271  if (e)
272  e->matched = true;
273  }
274 }
The envelope/body of an email.
Definition: email.h:37
struct Mailbox * mailbox
Current selected mailbox.
Definition: private.h:206
void * mutt_hash_int_find(const struct HashTable *table, unsigned int intkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:384
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:923
Log at debug level 2.
Definition: logging.h:41
void * mdata
Driver specific data.
Definition: mailbox.h:136
struct HashTable * uid_hash
Definition: private.h:236
int mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: string.c:287
IMAP-specific Mailbox data -.
Definition: private.h:216
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
bool matched
Search matches this Email.
Definition: email.h:68
+ Here is the call graph for this function:
+ Here is the caller graph for this function: