NeoMutt  2022-04-29-249-gaae397
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 "adata.h"
#include "mdata.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 83 of file search.c.

84{
85 int positives = 0;
86
87 const struct Pattern *pat = NULL;
88 SLIST_FOREACH(pat, patterns, entries)
89 {
90 positives += check_pattern(pat);
91 }
92
93 return positives;
94}
#define SLIST_FOREACH(var, head, field)
Definition: queue.h:231
static bool check_pattern(const struct Pattern *pat)
Check whether a pattern can be searched server-side.
Definition: search.c:57
A simple (non-regex) pattern.
Definition: lib.h:70
+ 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
trueSuccess
falseFailure

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 209 of file search.c.

211{
212 if (!check_pattern(pat))
213 return true;
214
215 if (pat->pat_not)
216 mutt_buffer_addstr(buf, "NOT ");
217
218 return pat->child ? compile_search_children(adata, pat, buf) :
219 compile_search_self(adata, pat, buf);
220}
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:233
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.
Definition: search.c:104
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:143
struct PatternList * child
Arguments to logical operation.
Definition: lib.h:83
bool pat_not
Pattern should be inverted (not)
Definition: lib.h:72
+ 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 57 of file search.c.

58{
59 switch (pat->op)
60 {
61 case MUTT_PAT_BODY:
62 case MUTT_PAT_HEADER:
64 if (pat->string_match)
65 return true;
66 break;
68 return true;
69 break;
70 default:
71 if (pat->child && check_pattern_list(pat->child))
72 return true;
73 break;
74 }
75 return false;
76}
@ MUTT_PAT_HEADER
Pattern matches email's header.
Definition: lib.h:148
@ MUTT_PAT_WHOLE_MSG
Pattern matches raw email text.
Definition: lib.h:150
@ MUTT_PAT_SERVERSEARCH
Server-side pattern matches.
Definition: lib.h:167
@ MUTT_PAT_BODY
Pattern matches email's body.
Definition: lib.h:147
static int check_pattern_list(const struct PatternList *patterns)
Check how many patterns in a list can be searched server-side.
Definition: search.c:83
bool string_match
Check a string for a match.
Definition: lib.h:74
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: lib.h:71
+ 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
trueSuccess
falseFailure

Definition at line 104 of file search.c.

106{
107 int clauses = check_pattern_list(pat->child);
108 if (clauses == 0)
109 return true;
110
111 mutt_buffer_addch(buf, '(');
112
113 struct Pattern *c;
114 SLIST_FOREACH(c, pat->child, entries)
115 {
116 if (!check_pattern(c))
117 continue;
118
119 if ((pat->op == MUTT_PAT_OR) && (clauses > 1))
120 mutt_buffer_addstr(buf, "OR ");
121
122 if (!compile_search(adata, c, buf))
123 return false;
124
125 if (clauses > 1)
126 mutt_buffer_addch(buf, ' ');
127
128 clauses--;
129 }
130
131 mutt_buffer_addch(buf, ')');
132 return true;
133}
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:248
@ MUTT_PAT_OR
Either pattern can match.
Definition: lib.h:131
static bool compile_search(const struct ImapAccountData *adata, const struct Pattern *pat, struct Buffer *buf)
Convert NeoMutt pattern to IMAP search.
Definition: search.c:209
+ 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
trueSuccess
falseFailure

Definition at line 143 of file search.c.

145{
146 char term[256] = { 0 };
147 char *delim = NULL;
148
149 switch (pat->op)
150 {
151 case MUTT_PAT_HEADER:
152 mutt_buffer_addstr(buf, "HEADER ");
153
154 /* extract header name */
155 delim = strchr(pat->p.str, ':');
156 if (!delim)
157 {
158 mutt_error(_("Header search without header name: %s"), pat->p.str);
159 return false;
160 }
161 *delim = '\0';
162 imap_quote_string(term, sizeof(term), pat->p.str, false);
163 mutt_buffer_addstr(buf, term);
164 mutt_buffer_addch(buf, ' ');
165
166 /* and field */
167 *delim = ':';
168 delim++;
169 SKIPWS(delim);
170 imap_quote_string(term, sizeof(term), delim, false);
171 mutt_buffer_addstr(buf, term);
172 break;
173 case MUTT_PAT_BODY:
174 mutt_buffer_addstr(buf, "BODY ");
175 imap_quote_string(term, sizeof(term), pat->p.str, false);
176 mutt_buffer_addstr(buf, term);
177 break;
179 mutt_buffer_addstr(buf, "TEXT ");
180 imap_quote_string(term, sizeof(term), pat->p.str, false);
181 mutt_buffer_addstr(buf, term);
182 break;
184 if (!(adata->capabilities & IMAP_CAP_X_GM_EXT_1))
185 {
186 mutt_error(_("Server-side custom search not supported: %s"), pat->p.str);
187 return false;
188 }
189 mutt_buffer_addstr(buf, "X-GM-RAW ");
190 imap_quote_string(term, sizeof(term), pat->p.str, false);
191 mutt_buffer_addstr(buf, term);
192 break;
193 }
194 return true;
195}
#define mutt_error(...)
Definition: logging.h:87
#define IMAP_CAP_X_GM_EXT_1
https://developers.google.com/gmail/imap/imap-extensions
Definition: private.h:142
void imap_quote_string(char *dest, size_t dlen, const char *src, bool quote_backtick)
Quote string according to IMAP rules.
Definition: util.c:837
#define _(a)
Definition: message.h:28
#define SKIPWS(ch)
Definition: string2.h:46
ImapCapFlags capabilities
Capability flags.
Definition: adata.h:55
union Pattern::@1 p
char * str
String, if string_match is set.
Definition: lib.h:87
+ 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 229 of file search.c.

230{
231 for (int i = 0; i < m->msg_count; i++)
232 {
233 struct Email *e = m->emails[i];
234 if (!e)
235 break;
236 e->matched = false;
237 }
238
239 if (check_pattern_list(pat) == 0)
240 return true;
241
242 struct Buffer buf;
243 mutt_buffer_init(&buf);
244 mutt_buffer_addstr(&buf, "UID SEARCH ");
245
247 const bool ok = compile_search(adata, SLIST_FIRST(pat), &buf) &&
249
250 FREE(&buf.data);
251 return ok;
252}
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:52
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:89
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
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:73
@ IMAP_EXEC_SUCCESS
Imap command executed or queued successfully.
Definition: private.h:84
#define FREE(x)
Definition: memory.h:43
#define SLIST_FIRST(head)
Definition: queue.h:229
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
String manipulation buffer.
Definition: buffer.h:34
The envelope/body of an email.
Definition: email.h:37
bool matched
Search matches this Email.
Definition: email.h:102
IMAP-specific Account data -.
Definition: adata.h:40
char * buf
Definition: adata.h:59
int msg_count
Total number of messages.
Definition: mailbox.h:88
struct Email ** emails
Array of Emails.
Definition: mailbox.h:96
+ 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 259 of file search.c.

260{
261 unsigned int uid;
262 struct Email *e = NULL;
263 struct ImapMboxData *mdata = adata->mailbox->mdata;
264
265 mutt_debug(LL_DEBUG2, "Handling SEARCH\n");
266
267 while ((s = imap_next_word((char *) s)) && (*s != '\0'))
268 {
269 if (!mutt_str_atoui(s, &uid))
270 continue;
271 e = mutt_hash_int_find(mdata->uid_hash, uid);
272 if (e)
273 e->matched = true;
274 }
275}
const char * mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: atoi.c:202
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
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:392
char * imap_next_word(char *s)
Find where the next IMAP word begins.
Definition: util.c:789
@ LL_DEBUG2
Log at debug level 2.
Definition: logging.h:41
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
IMAP-specific Mailbox data -.
Definition: mdata.h:39
void * mdata
Driver specific data.
Definition: mailbox.h:132
+ Here is the call graph for this function:
+ Here is the caller graph for this function: