summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-01-26 00:30:28 +0200
committerSergey Poznyakoff <gray@gnu.org>2019-01-26 01:05:52 +0200
commit3798a0f09da7fcaa6daa12e9ae483ebf99f7c46a (patch)
tree97c80866168b24c3c45f2d1961311d80b6ff1823
parentbc4d023a3810a7da6ede2cc522cdc34fa3129378 (diff)
downloadmailutils-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--NEWS11
-rw-r--r--imap4d/imap4d.h1
-rw-r--r--imap4d/search.c262
-rw-r--r--imap4d/util.c8
-rw-r--r--libmailutils/mailbox/header.c0
5 files changed, 241 insertions, 41 deletions
diff --git a/NEWS b/NEWS
index 84d36010c..4f5c0dec9 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
1GNU mailutils NEWS -- history of user-visible changes. 2019-01-23 1GNU mailutils NEWS -- history of user-visible changes. 2019-01-26
2Copyright (C) 2002-2019 Free Software Foundation, Inc. 2Copyright (C) 2002-2019 Free Software Foundation, Inc.
3See the end of file for copying conditions. 3See the end of file for copying conditions.
4 4
@@ -6,6 +6,15 @@ Please send mailutils bug reports to <bug-mailutils@gnu.org>.
6 6
7Version 3.5.90 (git) 7Version 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
15Both commands now properly descend into multipart message parts and
16decode messages, if necessary
17
9* Fixes in the 'mail' utility 18* Fixes in the 'mail' utility
10 19
11** New mailbox notation @ 20** New mailbox notation @
diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h
index 2ad339a30..b90d653a0 100644
--- a/imap4d/imap4d.h
+++ b/imap4d/imap4d.h
@@ -454,7 +454,6 @@ extern int util_parse_822_date (const char *date, time_t *timep,
454 enum datetime_parse_mode flag); 454 enum datetime_parse_mode flag);
455extern int util_parse_ctime_date (const char *date, time_t *timep, 455extern int util_parse_ctime_date (const char *date, time_t *timep,
456 enum datetime_parse_mode flag); 456 enum datetime_parse_mode flag);
457extern char *util_strcasestr (const char *haystack, const char *needle);
458extern char *util_localname (void); 457extern char *util_localname (void);
459 458
460void util_print_flags (mu_attribute_t attr); 459void util_print_flags (mu_attribute_t attr);
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
@@ -224,6 +225,7 @@ struct parsebuf
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 */
228 char *charset; /* Charset, other than US-ASCII requested */
227 229
228 struct search_node *tree; /* Parse tree */ 230 struct search_node *tree; /* Parse tree */
229 231
@@ -241,6 +243,7 @@ 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
@@ -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);
303 if (!available_charset (parsebuf.charset))
304 {
305 *err_text = "[BADCHARSET] Charset not supported";
300 return RESP_NO; 306 return RESP_NO;
301 } 307 }
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 */
@@ -796,15 +804,38 @@ search_run (struct parsebuf *pb)
796static int 804static int
797_scan_header (struct parsebuf *pb, char *name, char *value) 805_scan_header (struct parsebuf *pb, char *name, char *value)
798{ 806{
799 const char *hval; 807 char *hval;
800 mu_header_t header = NULL; 808 mu_header_t header = NULL;
809 int i, rc;
810 int result = 0;
801 811
802 mu_message_get_header (pb->msg, &header); 812 mu_message_get_header (pb->msg, &header);
803 if (mu_header_sget_value (header, name, &hval) == 0) 813
814 for (i = 1;
815 result == 0
816 && (rc = mu_header_aget_value_unfold_n (header, name, i, &hval)) == 0;
817 i++)
818 {
819 if (pb->charset)
820 {
821 char *tmp;
822 rc = mu_rfc2047_decode (pb->charset, hval, &tmp);
823 if (rc)
804 { 824 {
805 return util_strcasestr (hval, value) != NULL; 825 mu_diag_funcall (MU_DIAG_ERR, "mu_rfc2047_decode", hval, rc);
826 free (hval);
827 continue;
806 } 828 }
807 return 0; 829 free (hval);
830 hval = tmp;
831 }
832 result = mu_c_strcasestr (hval, value) != NULL;
833 free (hval);
834 }
835 if (!(rc == 0 || rc == MU_ERR_NOENT))
836 mu_diag_funcall (MU_DIAG_ERR, "mu_header_aget_value_unfold_n", NULL, rc);
837
838 return result;
808} 839}
809 840
810/* Get the value of Date: field and convert it to timestamp */ 841/* Get the value of Date: field and convert it to timestamp */
@@ -825,47 +856,192 @@ _header_date (struct parsebuf *pb, time_t *timep)
825static int 856static int
826_scan_header_all (struct parsebuf *pb, char *text) 857_scan_header_all (struct parsebuf *pb, char *text)
827{ 858{
828 const char *hval;
829 mu_header_t header = NULL; 859 mu_header_t header = NULL;
830 size_t fcount = 0; 860 size_t fcount = 0;
831 int i, rc; 861 int i, rc;
862 int result;
832 863
833 mu_message_get_header (pb->msg, &header); 864 mu_message_get_header (pb->msg, &header);
834 mu_header_get_field_count (header, &fcount); 865 mu_header_get_field_count (header, &fcount);
835 for (i = rc = 0; i < fcount; i++) 866 result = 0;
867 for (i = 1; result == 0 && i < fcount; i++)
836 { 868 {
837 if (mu_header_sget_field_value (header, i, &hval) == 0) 869 char *hval;
838 rc = util_strcasestr (hval, text) != NULL; 870
871 rc = mu_header_aget_field_value_unfold (header, i, &hval);
872 if (rc)
873 {
874 mu_diag_funcall (MU_DIAG_ERR, "mu_header_aget_field_value_unfold",
875 NULL, rc);
876 continue;
839 } 877 }
840 return rc; 878
879 if (pb->charset)
880 {
881 char *tmp;
882 rc = mu_rfc2047_decode (pb->charset, hval, &tmp);
883 if (rc)
884 {
885 mu_diag_funcall (MU_DIAG_ERR, "mu_rfc2047_decode", hval, rc);
886 free (hval);
887 continue;
888 }
889
890 free (hval);
891 hval = tmp;
892 }
893 result = mu_c_strcasestr (hval, text) != NULL;
894 free (hval);
895 }
896 return result;
841} 897}
842 898
843/* Scan body of the message for the occurrence of a substring */
844/* FIXME: The algorithm below is broken */
845static int 899static int
846_scan_body (struct parsebuf *pb, char *text) 900_match_text (struct parsebuf *pb, mu_message_t msg, mu_content_type_t ct,
901 char const *encoding,
902 char *text)
847{ 903{
848 mu_body_t body = NULL; 904 mu_body_t body;
849 mu_stream_t stream = NULL; 905 mu_stream_t str;
850 size_t size = 0, lines = 0;
851 char buffer[128];
852 size_t n = 0;
853 int rc; 906 int rc;
907 int result;
908 char *buffer = NULL;
909 size_t bufsize = 0;
910 size_t n;
911
912 mu_message_get_body (msg, &body);
913 mu_body_get_streamref (body, &str);
914
915 if (encoding)
916 {
917 mu_stream_t flt;