summaryrefslogtreecommitdiff
path: root/imap4d/search.c
diff options
context:
space:
mode:
Diffstat (limited to 'imap4d/search.c')
-rw-r--r--imap4d/search.c458
1 files changed, 329 insertions, 129 deletions
diff --git a/imap4d/search.c b/imap4d/search.c
index 1d28b570f..3c243eddf 100644
--- a/imap4d/search.c
+++ b/imap4d/search.c
@@ -15,6 +15,7 @@
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ 15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16 16
17#include "imap4d.h" 17#include "imap4d.h"
18#include <mailutils/assoc.h>
18 19
19/* 20/*
20 * This will be a royal pain in the arse to implement 21 * This will be a royal pain in the arse to implement
@@ -90,43 +91,43 @@ struct search_node
90}; 91};
91 92
92static void cond_msgset (struct parsebuf *, struct search_node *, 93static void cond_msgset (struct parsebuf *, struct search_node *,
93 struct value *, struct value *); 94 struct value *, struct value *);
94static void cond_bcc (struct parsebuf *, struct search_node *, 95static void cond_bcc (struct parsebuf *, struct search_node *,
95 struct value *, struct value *); 96 struct value *, struct value *);
96static void cond_before (struct parsebuf *, struct search_node *, 97static void cond_before (struct parsebuf *, struct search_node *,
97 struct value *, struct value *); 98 struct value *, struct value *);
98static void cond_body (struct parsebuf *, struct search_node *, 99static void cond_body (struct parsebuf *, struct search_node *,
99 struct value *, struct value *); 100 struct value *, struct value *);
100static void cond_cc (struct parsebuf *, struct search_node *, 101static void cond_cc (struct parsebuf *, struct search_node *,
101 struct value *, struct value *); 102 struct value *, struct value *);
102static void cond_from (struct parsebuf *, struct search_node *, 103static void cond_from (struct parsebuf *, struct search_node *,
103 struct value *, struct value *); 104 struct value *, struct value *);
104static void cond_header (struct parsebuf *, struct search_node *, 105static void cond_header (struct parsebuf *, struct search_node *,
105 struct value *, struct value *); 106 struct value *, struct value *);
106static void cond_keyword (struct parsebuf *, struct search_node *, 107static void cond_keyword (struct parsebuf *, struct search_node *,
107 struct value *, struct value *); 108 struct value *, struct value *);
108static void cond_larger (struct parsebuf *, struct search_node *, 109static void cond_larger (struct parsebuf *, struct search_node *,
109 struct value *, struct value *); 110 struct value *, struct value *);
110static void cond_on (struct parsebuf *, struct search_node *, 111static void cond_on (struct parsebuf *, struct search_node *,
111 struct value *, struct value *); 112 struct value *, struct value *);
112static void cond_sentbefore (struct parsebuf *, struct search_node *, 113static void cond_sentbefore (struct parsebuf *, struct search_node *,
113 struct value *, struct value *); 114 struct value *, struct value *);
114static void cond_senton (struct parsebuf *, struct search_node *, 115static void cond_senton (struct parsebuf *, struct search_node *,
115 struct value *, struct value *); 116 struct value *, struct value *);
116static void cond_sentsince (struct parsebuf *, struct search_node *, 117static void cond_sentsince (struct parsebuf *, struct search_node *,
117 struct value *, struct value *); 118 struct value *, struct value *);
118static void cond_since (struct parsebuf *, struct search_node *, 119static void cond_since (struct parsebuf *, struct search_node *,
119 struct value *, struct value *); 120 struct value *, struct value *);
120static void cond_smaller (struct parsebuf *, struct search_node *, 121static void cond_smaller (struct parsebuf *, struct search_node *,
121 struct value *, struct value *); 122 struct value *, struct value *);
122static void cond_subject (struct parsebuf *, struct search_node *, 123static void cond_subject (struct parsebuf *, struct search_node *,
123 struct value *, struct value *); 124 struct value *, struct value *);
124static void cond_text (struct parsebuf *, struct search_node *, 125static void cond_text (struct parsebuf *, struct search_node *,
125 struct value *, struct value *); 126 struct value *, struct value *);
126static void cond_to (struct parsebuf *, struct search_node *, 127static void cond_to (struct parsebuf *, struct search_node *,
127 struct value *, struct value *); 128 struct value *, struct value *);
128static void cond_uid (struct parsebuf *, struct search_node *, 129static void cond_uid (struct parsebuf *, struct search_node *,
129 struct value *, struct value *); 130 struct value *, struct value *);
130 131
131/* A basic condition structure */ 132/* A basic condition structure */
132struct cond 133struct cond
@@ -138,7 +139,7 @@ struct cond
138}; 139};
139 140
140/* Types are: s -- string 141/* Types are: s -- string
141 n -- number 142 n -- number
142 d -- date 143 d -- date
143 m -- message set 144 m -- message set
144*/ 145*/
@@ -213,23 +214,24 @@ struct mem_chain
213 214
214/* Maximum length of a token. Tokens longer than that are accepted, provided 215/* Maximum length of a token. Tokens longer than that are accepted, provided
215 that they are enclosed in doublequotes */ 216 that they are enclosed in doublequotes */
216#define MAXTOKEN 64 217#define MAXTOKEN 64
217 218
218/* Parse buffer structure */ 219/* Parse buffer structure */
219struct parsebuf 220struct parsebuf
220{ 221{
221 imap4d_tokbuf_t tok; /* Token buffer */ 222 imap4d_tokbuf_t tok; /* Token buffer */
222 int arg; /* Argument number */ 223 int arg; /* Argument number */
223 char *token; /* Current token */ 224 char *token; /* Current token */
224 int isuid; /* UIDs instead of msgnos are required */ 225 int isuid; /* UIDs instead of msgnos are required */
225 char *err_mesg; /* Error message if a parse error occured */ 226 char *err_mesg; /* Error message if a parse error occured */
226 struct mem_chain *alloc; /* Chain of objects allocated during parsing */ 227 struct mem_chain *alloc; /* Chain of objects allocated during parsing */
227 228 char *charset; /* Charset, other than US-ASCII requested */
229
228 struct search_node *tree; /* Parse tree */ 230 struct search_node *tree; /* Parse tree */
229 231
230 /* Execution time only: */ 232 /* Execution time only: */
231 size_t msgno; /* Number of current message */ 233 size_t msgno; /* Number of current message */
232 mu_message_t msg; /* Current message */ 234 mu_message_t msg; /* Current message */
233}; 235};
234 236
235static void parse_free_mem (struct parsebuf *pb); 237static void parse_free_mem (struct parsebuf *pb);
@@ -241,37 +243,38 @@ static struct search_node *parse_search_key (struct parsebuf *pb);
241static int parse_gettoken (struct parsebuf *pb, int req); 243static int parse_gettoken (struct parsebuf *pb, int req);
242static int search_run (struct parsebuf *pb); 244static int search_run (struct parsebuf *pb);
243static void do_search (struct parsebuf *pb); 245static void do_search (struct parsebuf *pb);
246static int available_charset (const char *charset);
244 247
245/* 248/*
2466.4.4. SEARCH Command 2496.4.4. SEARCH Command
247 250
248 Arguments: OPTIONAL [CHARSET] specification 251 Arguments: OPTIONAL [CHARSET] specification
249 searching criteria (one or more) 252 searching criteria (one or more)
250 253
251 Responses: REQUIRED untagged response: SEARCH 254 Responses: REQUIRED untagged response: SEARCH
252 255
253 Result: OK - search completed 256 Result: OK - search completed
254 NO - search error: can't search that [CHARSET] or 257 NO - search error: can't search that [CHARSET] or
255 criteria 258 criteria
256 BAD - command unknown or arguments invalid 259 BAD - command unknown or arguments invalid
257*/ 260*/
258 261
259int 262int
260imap4d_search (struct imap4d_session *session, 263imap4d_search (struct imap4d_session *session,
261 struct imap4d_command *command, imap4d_tokbuf_t tok) 264 struct imap4d_command *command, imap4d_tokbuf_t tok)
262{ 265{
263 int rc; 266 int rc;
264 char *err_text= ""; 267 char *err_text= "";
265 268
266 rc = imap4d_search0 (tok, 0, &err_text); 269 rc = imap4d_search0 (tok, 0, &err_text);
267 return io_completion_response (command, rc, "%s", err_text); 270 return io_completion_response (command, rc, "%s", err_text);
268} 271}
269 272
270int 273int
271imap4d_search0 (imap4d_tokbuf_t tok, int isuid, char **err_text) 274imap4d_search0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
272{ 275{
273 struct parsebuf parsebuf; 276 struct parsebuf parsebuf;
274 277
275 memset (&parsebuf, 0, sizeof(parsebuf)); 278 memset (&parsebuf, 0, sizeof(parsebuf));
276 parsebuf.tok = tok; 279 parsebuf.tok = tok;
277 parsebuf.arg = IMAP4_ARG_1 + !!isuid; 280 parsebuf.arg = IMAP4_ARG_1 + !!isuid;
@@ -284,7 +287,7 @@ imap4d_search0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
284 *err_text = "Too few args"; 287 *err_text = "Too few args";
285 return RESP_BAD; 288 return RESP_BAD;
286 } 289 }
287 290
288 if (mu_c_strcasecmp (parsebuf.token, "CHARSET") == 0) 291 if (mu_c_strcasecmp (parsebuf.token, "CHARSET") == 0)
289 { 292 {
290 if (!parse_gettoken (&parsebuf, 0)) 293 if (!parse_gettoken (&parsebuf, 0))
@@ -296,16 +299,21 @@ imap4d_search0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
296 /* Currently only ASCII is supported */ 299 /* Currently only ASCII is supported */
297 if (mu_c_strcasecmp (parsebuf.token, "US-ASCII")) 300 if (mu_c_strcasecmp (parsebuf.token, "US-ASCII"))
298 { 301 {
299 *err_text = "Charset not supported"; 302 parsebuf.charset = parse_strdup (&parsebuf, parsebuf.token);
300 return RESP_NO; 303 if (!available_charset (parsebuf.charset))
304 {
305 *err_text = "[BADCHARSET] Charset not supported";
306 return RESP_NO;
307 }
301 } 308 }
309 else
310 parsebuf.charset = NULL;
302 311
303 if (!parse_gettoken (&parsebuf, 0)) 312 if (!parse_gettoken (&parsebuf, 0))
304 { 313 {
305 *err_text = "Too few args"; 314 *err_text = "Too few args";
306 return RESP_BAD; 315 return RESP_BAD;
307 } 316 }
308
309 } 317 }
310 318
311 /* Compile the expression */ 319 /* Compile the expression */
@@ -323,12 +331,12 @@ imap4d_search0 (imap4d_tokbuf_t tok, int isuid, char **err_text)
323 *err_text = "Junk at the end of statement"; 331 *err_text = "Junk at the end of statement";
324 return RESP_BAD;