diff options
Diffstat (limited to 'imap4d/search.c')
-rw-r--r-- | imap4d/search.c | 458 |
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 | ||
92 | static void cond_msgset (struct parsebuf *, struct search_node *, | 93 | static void cond_msgset (struct parsebuf *, struct search_node *, |
93 | struct value *, struct value *); | 94 | struct value *, struct value *); |
94 | static void cond_bcc (struct parsebuf *, struct search_node *, | 95 | static void cond_bcc (struct parsebuf *, struct search_node *, |
95 | struct value *, struct value *); | 96 | struct value *, struct value *); |
96 | static void cond_before (struct parsebuf *, struct search_node *, | 97 | static void cond_before (struct parsebuf *, struct search_node *, |
97 | struct value *, struct value *); | 98 | struct value *, struct value *); |
98 | static void cond_body (struct parsebuf *, struct search_node *, | 99 | static void cond_body (struct parsebuf *, struct search_node *, |
99 | struct value *, struct value *); | 100 | struct value *, struct value *); |
100 | static void cond_cc (struct parsebuf *, struct search_node *, | 101 | static void cond_cc (struct parsebuf *, struct search_node *, |
101 | struct value *, struct value *); | 102 | struct value *, struct value *); |
102 | static void cond_from (struct parsebuf *, struct search_node *, | 103 | static void cond_from (struct parsebuf *, struct search_node *, |
103 | struct value *, struct value *); | 104 | struct value *, struct value *); |
104 | static void cond_header (struct parsebuf *, struct search_node *, | 105 | static void cond_header (struct parsebuf *, struct search_node *, |
105 | struct value *, struct value *); | 106 | struct value *, struct value *); |
106 | static void cond_keyword (struct parsebuf *, struct search_node *, | 107 | static void cond_keyword (struct parsebuf *, struct search_node *, |
107 | struct value *, struct value *); | 108 | struct value *, struct value *); |
108 | static void cond_larger (struct parsebuf *, struct search_node *, | 109 | static void cond_larger (struct parsebuf *, struct search_node *, |
109 | struct value *, struct value *); | 110 | struct value *, struct value *); |
110 | static void cond_on (struct parsebuf *, struct search_node *, | 111 | static void cond_on (struct parsebuf *, struct search_node *, |
111 | struct value *, struct value *); | 112 | struct value *, struct value *); |
112 | static void cond_sentbefore (struct parsebuf *, struct search_node *, | 113 | static void cond_sentbefore (struct parsebuf *, struct search_node *, |
113 | struct value *, struct value *); | 114 | struct value *, struct value *); |
114 | static void cond_senton (struct parsebuf *, struct search_node *, | 115 | static void cond_senton (struct parsebuf *, struct search_node *, |
115 | struct value *, struct value *); | 116 | struct value *, struct value *); |
116 | static void cond_sentsince (struct parsebuf *, struct search_node *, | 117 | static void cond_sentsince (struct parsebuf *, struct search_node *, |
117 | struct value *, struct value *); | 118 | struct value *, struct value *); |
118 | static void cond_since (struct parsebuf *, struct search_node *, | 119 | static void cond_since (struct parsebuf *, struct search_node *, |
119 | struct value *, struct value *); | 120 | struct value *, struct value *); |
120 | static void cond_smaller (struct parsebuf *, struct search_node *, | 121 | static void cond_smaller (struct parsebuf *, struct search_node *, |
121 | struct value *, struct value *); | 122 | struct value *, struct value *); |
122 | static void cond_subject (struct parsebuf *, struct search_node *, | 123 | static void cond_subject (struct parsebuf *, struct search_node *, |
123 | struct value *, struct value *); | 124 | struct value *, struct value *); |
124 | static void cond_text (struct parsebuf *, struct search_node *, | 125 | static void cond_text (struct parsebuf *, struct search_node *, |
125 | struct value *, struct value *); | 126 | struct value *, struct value *); |
126 | static void cond_to (struct parsebuf *, struct search_node *, | 127 | static void cond_to (struct parsebuf *, struct search_node *, |
127 | struct value *, struct value *); | 128 | struct value *, struct value *); |
128 | static void cond_uid (struct parsebuf *, struct search_node *, | 129 | static 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 */ |
132 | struct cond | 133 | struct 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 */ |
219 | struct parsebuf | 220 | struct 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 | ||
235 | static void parse_free_mem (struct parsebuf *pb); | 237 | static void parse_free_mem (struct parsebuf *pb); |
@@ -241,37 +243,38 @@ static struct search_node *parse_search_key (struct parsebuf *pb); | |||
241 | static int parse_gettoken (struct parsebuf *pb, int req); | 243 | static int parse_gettoken (struct parsebuf *pb, int req); |
242 | static int search_run (struct parsebuf *pb); | 244 | static int search_run (struct parsebuf *pb); |
243 | static void do_search (struct parsebuf *pb); | 245 | static void do_search (struct parsebuf *pb); |
246 | static int available_charset (const char *charset); | ||
244 | 247 | ||
245 | /* | 248 | /* |
246 | 6.4.4. SEARCH Command | 249 | 6.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 | ||
259 | int | 262 | int |
260 | imap4d_search (struct imap4d_session *session, | 263 | imap4d_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 | ||
270 | int | 273 | int |
271 | imap4d_search0 (imap4d_tokbuf_t tok, int isuid, char **err_text) | 274 | imap4d_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; |