diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-01-26 00:30:28 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-01-26 01:05:52 +0200 |
commit | 3798a0f09da7fcaa6daa12e9ae483ebf99f7c46a (patch) | |
tree | 97c80866168b24c3c45f2d1961311d80b6ff1823 | |
parent | bc4d023a3810a7da6ede2cc522cdc34fa3129378 (diff) | |
download | mailutils-3798a0f09da7fcaa6daa12e9ae483ebf99f7c46a.tar.gz mailutils-3798a0f09da7fcaa6daa12e9ae483ebf99f7c46a.tar.bz2 |
imap4d: implement SEARCH CHARSET; fix BODY and TEXT searches.
* imap4d/search.c: Implement proper BODY searches. Implement CHARSET.
* imap4d/util.c (util_strcasestr): Remove. Use mu_c_strcasestr instead.
* imap4d/imap4d.h: Likewise.
* NEWS: Document changes.
-rw-r--r-- | NEWS | 11 | ||||
-rw-r--r-- | imap4d/imap4d.h | 1 | ||||
-rw-r--r-- | imap4d/search.c | 458 | ||||
-rw-r--r-- | imap4d/util.c | 8 | ||||
-rw-r--r-- | libmailutils/mailbox/header.c | 4 |
5 files changed, 341 insertions, 141 deletions
@@ -1,2 +1,2 @@ | |||
1 | GNU mailutils NEWS -- history of user-visible changes. 2019-01-23 | 1 | GNU mailutils NEWS -- history of user-visible changes. 2019-01-26 |
2 | Copyright (C) 2002-2019 Free Software Foundation, Inc. | 2 | Copyright (C) 2002-2019 Free Software Foundation, Inc. |
@@ -8,2 +8,11 @@ Version 3.5.90 (git) | |||
8 | 8 | ||
9 | * imap4d: SEARCH command | ||
10 | |||
11 | ** Implemented SEARCH CHARSET | ||
12 | |||
13 | ** Improved SEARCH BODY and SEARCH TEXT commands | ||
14 | |||
15 | Both commands now properly descend into multipart message parts and | ||
16 | decode messages, if necessary | ||
17 | |||
9 | * Fixes in the 'mail' utility | 18 | * Fixes in the 'mail' utility |
diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h index 2ad339a30..b90d653a0 100644 --- a/imap4d/imap4d.h +++ b/imap4d/imap4d.h | |||
@@ -456,3 +456,2 @@ extern int util_parse_ctime_date (const char *date, time_t *timep, | |||
456 | enum datetime_parse_mode flag); | 456 | enum datetime_parse_mode flag); |
457 | extern char *util_strcasestr (const char *haystack, const char *needle); | ||
458 | extern char *util_localname (void); | 457 | extern char *util_localname (void); |
diff --git a/imap4d/search.c b/imap4d/search.c index 1d28b570f..3c243eddf 100644 --- a/imap4d/search.c +++ b/imap4d/search.c | |||
@@ -17,2 +17,3 @@ | |||
17 | #include "imap4d.h" | 17 | #include "imap4d.h" |
18 | #include <mailutils/assoc.h> | ||
18 | 19 | ||
@@ -92,3 +93,3 @@ struct search_node | |||
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 *, |
@@ -96,21 +97,21 @@ static void cond_bcc (struct parsebuf *, struct search_node *, | |||
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 *, |
@@ -118,13 +119,13 @@ static void cond_sentsince (struct parsebuf *, struct search_node *, | |||
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 | ||
@@ -140,3 +141,3 @@ struct cond | |||
140 | /* Types are: s -- string | 141 | /* Types are: s -- string |
141 | n -- number | 142 | n -- number |
142 | d -- date | 143 | d -- date |
@@ -215,3 +216,3 @@ struct mem_chain | |||
215 | that they are enclosed in doublequotes */ | 216 | that they are enclosed in doublequotes */ |
216 | #define MAXTOKEN 64 | 217 | #define MAXTOKEN 64 |
217 | 218 | ||
@@ -220,14 +221,15 @@ 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 | }; |
@@ -243,2 +245,3 @@ 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 | ||
@@ -248,3 +251,3 @@ static void do_search (struct parsebuf *pb); | |||
248 | Arguments: OPTIONAL [CHARSET] specification | 251 | Arguments: OPTIONAL [CHARSET] specification |
249 | searching criteria (one or more) | 252 | searching criteria (one or more) |
250 | 253 | ||
@@ -253,5 +256,5 @@ static void do_search (struct parsebuf *pb); | |||
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 | */ |
@@ -260,3 +263,3 @@ 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 | { |
@@ -264,3 +267,3 @@ imap4d_search (struct imap4d_session *session, | |||
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); |
@@ -268,3 +271,3 @@ imap4d_search (struct imap4d_session *session, | |||
268 | } | 271 | } |
269 | 272 | ||
270 | int | 273 | int |
@@ -273,3 +276,3 @@ imap4d_search0 (imap4d_tokbuf_t tok, int isuid, char **err_text) | |||
273 | struct parsebuf parsebuf; | 276 | struct parsebuf parsebuf; |
274 | 277 | ||
275 | memset (&parsebuf, 0, sizeof(parsebuf)); | 278 | memset (&parsebuf, 0, sizeof(parsebuf)); |
@@ -286,3 +289,3 @@ imap4d_search0 (imap4d_tokbuf_t tok, int isuid, char **err_text) | |||
286 | } | 289 | } |
287 | 290 | ||
288 | if (mu_c_strcasecmp (parsebuf.token, "CHARSET") == 0) | 291 | if (mu_c_strcasecmp (parsebuf.token, "CHARSET") == 0) |
@@ -298,5 +301,11 @@ imap4d_search0 (imap4d_tokbuf_t tok, int isuid, char **err_text) | |||
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 | ||
@@ -307,3 +316,2 @@ imap4d_search0 (imap4d_tokbuf_t tok, int isuid, char **err_text) | |||
307 | } | 316 | } |
308 | |||
309 | } | 317 | } |
@@ -325,8 +333,8 @@ imap4d_search0 (imap4d_tokbuf_t tok, int isuid, char **err_text) | |||
325 | } | 333 | } |
326 | 334 | ||
327 | /* Execute compiled expression */ | 335 | /* Execute compiled expression */ |
328 | do_search (&parsebuf); | 336 | do_search (&parsebuf); |
329 | 337 | ||
330 | parse_free_mem (&parsebuf); | 338 | parse_free_mem (&parsebuf); |
331 | 339 | ||
332 | *err_text = "Completed"; | 340 | *err_text = "Completed"; |
@@ -341,3 +349,3 @@ do_search (struct parsebuf *pb) | |||
341 | size_t count = 0; | 349 | size_t count = 0; |
342 | 350 | ||
343 | mu_mailbox_messages_count (mbox, &count); | 351 | mu_mailbox_messages_count (mbox, &count); |
@@ -419,3 +427,3 @@ parse_alloc (struct parsebuf *pb, size_t size) | |||
419 | 427 | ||
420 | /* Create a copy of the string. */ | 428 | /* Create a copy of the string. */ |
421 | char * | 429 | char * |
@@ -447,3 +455,3 @@ parse_msgset_create (struct parsebuf *pb, mu_mailbox_t mbox, int flags) | |||
447 | search_key_list : search_key | 455 | search_key_list : search_key |
448 | | search_key_list search_key | 456 | | search_key_list search_key |
449 | ; | 457 | ; |
@@ -451,3 +459,3 @@ parse_msgset_create (struct parsebuf *pb, mu_mailbox_t mbox, int flags) | |||
451 | search_key : simple_key | 459 | search_key : simple_key |
452 | | NOT simple_key | 460 | | NOT simple_key |
453 | | OR simple_key simple_key | 461 | | OR simple_key simple_key |
@@ -488,3 +496,3 @@ parse_search_key (struct parsebuf *pb) | |||
488 | struct search_node *node; |