NeoMutt  2024-03-23-23-gec7045
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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.
 
static bool compile_search (const struct ImapAccountData *adata, const struct Pattern *pat, struct Buffer *buf)
 Convert NeoMutt pattern to IMAP search.
 
static bool check_pattern (const struct Pattern *pat)
 Check whether a pattern can be searched server-side.
 
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.
 
static bool compile_search_self (const struct ImapAccountData *adata, const struct Pattern *pat, struct Buffer *buf)
 Compile a search command for a pattern.
 
bool imap_search (struct Mailbox *m, const struct PatternList *pat)
 Find messages in mailbox matching a pattern.
 
void cmd_parse_search (struct ImapAccountData *adata, const char *s)
 Store SEARCH response for later use.
 

Detailed Description

IMAP search routines.

Authors
  • Pietro Cerutti
  • 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 81 of file search.c.

82{
83 int positives = 0;
84
85 const struct Pattern *pat = NULL;
86 SLIST_FOREACH(pat, patterns, entries)
87 {
88 positives += check_pattern(pat);
89 }
90
91 return positives;
92}
#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:55
A simple (non-regex) pattern.
Definition: lib.h:77
+ 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 207 of file search.c.

209{
210 if (!check_pattern(pat))
211 return true;
212
213 if (pat->pat_not)
214 buf_addstr(buf, "NOT ");
215
216 return pat->child ? compile_search_children(adata, pat, buf) :
217 compile_search_self(adata, pat, buf);
218}
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:243
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:102
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:141
struct PatternList * child
Arguments to logical operation.
Definition: lib.h:90
bool pat_not
Pattern should be inverted (not)
Definition: lib.h:79
+ 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 55 of file search.c.

56{
57 switch (pat->op)
58 {
59 case MUTT_PAT_BODY:
60 case MUTT_PAT_HEADER:
62 if (pat->string_match)
63 return true;
64 break;
66 return true;
67 break;
68 default:
69 if (pat->child && check_pattern_list(pat->child))
70 return true;
71 break;
72 }
73 return false;
74}
@ MUTT_PAT_HEADER
Pattern matches email's header.
Definition: lib.h:156
@ MUTT_PAT_WHOLE_MSG
Pattern matches raw email text.
Definition: lib.h:158
@ MUTT_PAT_SERVERSEARCH
Server-side pattern matches.
Definition: lib.h:175
@ MUTT_PAT_BODY
Pattern matches email's body.
Definition: lib.h:155
static int check_pattern_list(const struct PatternList *patterns)
Check how many patterns in a list can be searched server-side.
Definition: search.c:81
bool string_match
Check a string for a match.
Definition: lib.h:81
short op
Operation, e.g. MUTT_PAT_SCORE.
Definition: lib.h:78
+ 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 102 of file search.c.

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

143{
144 char term[256] = { 0 };
145 char *delim = NULL;
146
147 switch (pat->op)
148 {
149 case MUTT_PAT_HEADER:
150 buf_addstr(buf, "HEADER ");
151
152 /* extract header name */
153 delim = strchr(pat->p.str, ':');
154 if (!delim)
155 {
156 mutt_error(_("Header search without header name: %s"), pat->p.str);
157 return false;
158 }
159 *delim = '\0';
160 imap_quote_string(term, sizeof(term), pat->p.str, false);
161 buf_addstr(buf, term);
162 buf_addch(buf, ' ');
163
164 /* and field */
165 *delim = ':';
166 delim++;
167 SKIPWS(delim);
168 imap_quote_string(term, sizeof(term), delim, false);
169 buf_addstr(buf, term);
170 break;
171 case MUTT_PAT_BODY:
172 buf_addstr(buf, "BODY ");
173 imap_quote_string(term, sizeof(term), pat->p.str, false);
174 buf_addstr(buf, term);
175 break;
177 buf_addstr(buf, "TEXT ");
178 imap_quote_string(term, sizeof(term), pat->p.str, false);
179 buf_addstr(buf, term);
180 break;
182 if (!(adata->capabilities & IMAP_CAP_X_GM_EXT_1))
183 {
184 mutt_error(_("Server-side custom search not supported: %s"), pat->p.str);
185 return false;
186 }
187 buf_addstr(buf, "X-GM-RAW ");
188 imap_quote_string(term, sizeof(term), pat->p.str, false);
189 buf_addstr(buf, term);
190 break;
191 }
192 return true;
193}
#define mutt_error(...)
Definition: logging2.h:92
#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:847
#define _(a)
Definition: message.h:28
#define SKIPWS(ch)
Definition: string2.h:45
ImapCapFlags capabilities
Capability flags.
Definition: adata.h:55
union Pattern::@1 p
char * str
String, if string_match is set.
Definition: lib.h:94
+ 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 227 of file search.c.

228{
229 for (int i = 0; i < m->msg_count; i++)
230 {
231 struct Email *e = m->emails[i];
232 if (!e)
233 break;
234 e->matched = false;
235 }
236
237 if (check_pattern_list(pat) == 0)
238 return true;
239
240 struct Buffer *buf = buf_pool_get();
241 buf_addstr(buf, "UID SEARCH ");
242
244 const bool ok = compile_search(adata, SLIST_FIRST(pat), buf) &&
246
248 return ok;
249}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:97
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:123
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:1307
#define IMAP_CMD_NO_FLAGS
No flags are set.
Definition: private.h:71
@ IMAP_EXEC_SUCCESS
Imap command executed or queued successfully.
Definition: private.h:82
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
#define SLIST_FIRST(head)
Definition: queue.h:229
void * adata
Private data (for Mailbox backends)
Definition: account.h:42
String manipulation buffer.
Definition: buffer.h:36
The envelope/body of an email.
Definition: email.h:39
bool matched
Search matches this Email.
Definition: email.h:105
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 256 of file search.c.

257{
258 unsigned int uid;
259 struct Email *e = NULL;
260 struct ImapMboxData *mdata = adata->mailbox->mdata;
261
262 mutt_debug(LL_DEBUG2, "Handling SEARCH\n");
263
264 while ((s = imap_next_word((char *) s)) && (*s != '\0'))
265 {
266 if (!mutt_str_atoui(s, &uid))
267 continue;
268 e = mutt_hash_int_find(mdata->uid_hash, uid);
269 if (e)
270 e->matched = true;
271 }
272}
const char * mutt_str_atoui(const char *str, unsigned int *dst)
Convert ASCII string to an unsigned integer.
Definition: atoi.c:214
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
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:785
@ LL_DEBUG2
Log at debug level 2.
Definition: logging2.h:44
struct Mailbox * mailbox
Current selected mailbox.
Definition: adata.h:76
IMAP-specific Mailbox data -.
Definition: mdata.h:40
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: