Commit 5e5b68fd 5e5b68fd028495f7076a576df26962bbdf51ac63 by Sergey Poznyakoff

imap4d: fix returned INTERNALDATE and date searches.

INTERNALDATE now includes a meaningful timezone information (it
used to return +0000).

Date searches disregard the time and timezone of the INTERNALDATE
or Date: header, as mandated by RFC 3501.

* libmailutils/base/date.c (mu_parse_ctime_date_time): In the absence
of TZ in ctime strings, return local time zone.

* imap4d/io.c (imap4d_tokbuf_getline): Kill trailing whitespace.

* imap4d/util.c (adjust_tm): New function.
(util_parse_internal_date)
(util_parse_822_date)
(util_parse_ctime_date): Take three arguments, the third one controlling
what information to return. All uses updated.
* imap4d/fetch.c (_frt_internaldate): Return meaningful timezone.
If all else fails, use local TZ.
* imap4d/imap4d.h (datetime_parse_mode): New enum.
(util_parse_internal_date)
(util_parse_822_date)
(util_parse_ctime_date): Change signature.
* imap4d/search.c (parse_simple_key)
(_header_date,cond_before,cond_on,cond_since): Use datetime_date_only mode.

* testsuite/spool/search.mbox: New file.
* testsuite/spool/DISTFILES: Add search.mbox
* imap4d/testsuite/lib/imap4d.exp (imap4d_start): New option -mbox.
* imap4d/testsuite/imap4d/search.exp: Rewrite.

* imap4d/testsuite/imap4d/create.exp: Account for TZ part in internaldate
strings, which may vary.
* imap4d/testsuite/imap4d/fetch.exp: Likewise.
* imap4d/testsuite/imap4d/list.exp: List the new mailbox.
1 parent e759db27
...@@ -79,7 +79,7 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *date_time, char *text, ...@@ -79,7 +79,7 @@ imap4d_append0 (mu_mailbox_t mbox, int flags, char *date_time, char *text,
79 message is set to the current date and time by default. */ 79 message is set to the current date and time by default. */
80 if (date_time) 80 if (date_time)
81 { 81 {
82 if (util_parse_internal_date (date_time, &t)) 82 if (util_parse_internal_date (date_time, &t, datetime_default))
83 { 83 {
84 *err_text = "Invalid date/time format"; 84 *err_text = "Invalid date/time format";
85 return 1; 85 return 1;
......
...@@ -862,19 +862,34 @@ _frt_internaldate (struct fetch_function_closure *ffc, ...@@ -862,19 +862,34 @@ _frt_internaldate (struct fetch_function_closure *ffc,
862 struct tm tm, *tmp = NULL; 862 struct tm tm, *tmp = NULL;
863 mu_timezone tz; 863 mu_timezone tz;
864 char datebuf[sizeof ("13-Jul-2002 00:00:00")]; 864 char datebuf[sizeof ("13-Jul-2002 00:00:00")];
865 int tzoff;
866 int tzh = 0, tzm = 0;
865 867
866 mu_message_get_envelope (frt->msg, &env); 868 mu_message_get_envelope (frt->msg, &env);
867 if (mu_envelope_sget_date (env, &date) == 0 869 if (mu_envelope_sget_date (env, &date) == 0
868 && mu_parse_ctime_date_time (&date, &tm, &tz) == 0) 870 && mu_parse_ctime_date_time (&date, &tm, &tz) == 0)
871 {
869 tmp = &tm; 872 tmp = &tm;
873 tzoff = tz.utc_offset;
874 }
870 else 875 else
871 { 876 {
872 time_t t = time (NULL); 877 time_t t;
878 struct timeval stv;
879 struct timezone stz;
880
881 gettimeofday(&stv, &stz);
882 t = stv.tv_sec;
883 tzoff = - stz.tz_minuteswest;
873 tmp = localtime (&t); 884 tmp = localtime (&t);
874 } 885 }
886 tzh = tzoff / 3600;
887 if (tzoff < 0)
888 tzoff = - tzoff;
889 tzm = tzoff % 3600;
875 mu_strftime (datebuf, sizeof (datebuf), "%d-%b-%Y %H:%M:%S", tmp); 890 mu_strftime (datebuf, sizeof (datebuf), "%d-%b-%Y %H:%M:%S", tmp);
876 io_sendf ("%s", ffc->name); 891 io_sendf ("%s", ffc->name);
877 io_sendf (" \"%s +0000\"", datebuf); 892 io_sendf (" \"%s %+03d%02d\"", datebuf, tzh, tzm);
878 return 0; 893 return 0;
879 } 894 }
880 895
......
...@@ -367,9 +367,20 @@ extern char *util_getfullpath (const char *, const char *); ...@@ -367,9 +367,20 @@ extern char *util_getfullpath (const char *, const char *);
367 extern int util_msgset (char *, size_t **, int *, int); 367 extern int util_msgset (char *, size_t **, int *, int);
368 extern struct imap4d_command *util_getcommand (char *, 368 extern struct imap4d_command *util_getcommand (char *,
369 struct imap4d_command []); 369 struct imap4d_command []);
370 extern int util_parse_internal_date (char *date, time_t *timep); 370
371 extern int util_parse_822_date (const char *date, time_t *timep); 371 enum datetime_parse_mode /* how to parse date/time strings */
372 extern int util_parse_ctime_date (const char *date, time_t *timep); 372 {
373 datetime_default, /* default mode */
374 datetime_date_only, /* return only date part, ignore time and TZ */
375 datetime_time_only /* return only time and TZ, ignore date */
376 };
377
378 extern int util_parse_internal_date (char *date, time_t *timep,
379 enum datetime_parse_mode flag);
380 extern int util_parse_822_date (const char *date, time_t *timep,
381 enum datetime_parse_mode flag);
382 extern int util_parse_ctime_date (const char *date, time_t *timep,
383 enum datetime_parse_mode flag);
373 extern char *util_strcasestr (const char *haystack, const char *needle); 384 extern char *util_strcasestr (const char *haystack, const char *needle);
374 extern char *util_localname (void); 385 extern char *util_localname (void);
375 386
......
...@@ -548,6 +548,8 @@ imap4d_tokbuf_getline (struct imap4d_tokbuf *tok) ...@@ -548,6 +548,8 @@ imap4d_tokbuf_getline (struct imap4d_tokbuf *tok)
548 tok->buffer[--tok->level] = 0; 548 tok->buffer[--tok->level] = 0;
549 if (tok->buffer[tok->level - 1] == '\r') 549 if (tok->buffer[tok->level - 1] == '\r')
550 tok->buffer[--tok->level] = 0; 550 tok->buffer[--tok->level] = 0;
551 while (tok->level > 0 && mu_isblank (tok->buffer[tok->level-1]))
552 tok->buffer[--tok->level] = 0;
551 return level; 553 return level;
552 } 554 }
553 555
......
...@@ -670,7 +670,8 @@ parse_simple_key (struct parsebuf *pb) ...@@ -670,7 +670,8 @@ parse_simple_key (struct parsebuf *pb)
670 break; 670 break;
671 671
672 case 'd': /* date */ 672 case 'd': /* date */
673 if (util_parse_internal_date (pb->token, &time)) 673 if (util_parse_internal_date (pb->token, &time,
674 datetime_date_only))
674 { 675 {
675 pb->err_mesg = "Bad date format"; 676 pb->err_mesg = "Bad date format";
676 return NULL; 677 return NULL;
...@@ -801,7 +802,7 @@ _header_date (struct parsebuf *pb, time_t *timep) ...@@ -801,7 +802,7 @@ _header_date (struct parsebuf *pb, time_t *timep)
801 802
802 mu_message_get_header (pb->msg, &header); 803 mu_message_get_header (pb->msg, &header);
803 if (mu_header_sget_value (header, "Date", &hval) == 0 804 if (mu_header_sget_value (header, "Date", &hval) == 0
804 && util_parse_822_date (hval, timep)) 805 && util_parse_822_date (hval, timep, datetime_date_only))
805 return 0; 806 return 0;
806 return 1; 807 return 1;
807 } 808 }
...@@ -893,7 +894,7 @@ cond_before (struct parsebuf *pb, struct search_node *node, struct value *arg, ...@@ -893,7 +894,7 @@ cond_before (struct parsebuf *pb, struct search_node *node, struct value *arg,
893 retval->v.number = 0; 894 retval->v.number = 0;
894 else 895 else
895 { 896 {
896 util_parse_ctime_date (date, &mesg_time); 897 util_parse_ctime_date (date, &mesg_time, datetime_date_only);
897 retval->v.number = mesg_time < t; 898 retval->v.number = mesg_time < t;
898 } 899 }
899 } 900 }
...@@ -980,7 +981,7 @@ cond_on (struct parsebuf *pb, struct search_node *node, struct value *arg, ...@@ -980,7 +981,7 @@ cond_on (struct parsebuf *pb, struct search_node *node, struct value *arg,
980 retval->v.number = 0; 981 retval->v.number = 0;
981 else 982 else
982 { 983 {
983 util_parse_ctime_date (date, &mesg_time); 984 util_parse_ctime_date (date, &mesg_time, datetime_date_only);
984 retval->v.number = t <= mesg_time && mesg_time <= t + 86400; 985 retval->v.number = t <= mesg_time && mesg_time <= t + 86400;
985 } 986 }
986 } 987 }
...@@ -1038,7 +1039,7 @@ cond_since (struct parsebuf *pb, struct search_node *node, struct value *arg, ...@@ -1038,7 +1039,7 @@ cond_since (struct parsebuf *pb, struct search_node *node, struct value *arg,
1038 retval->v.number = 0; 1039 retval->v.number = 0;
1039 else 1040 else
1040 { 1041 {
1041 util_parse_ctime_date (date, &mesg_time); 1042 util_parse_ctime_date (date, &mesg_time, datetime_date_only);
1042 retval->v.number = mesg_time >= t; 1043 retval->v.number = mesg_time >= t;
1043 } 1044 }
1044 } 1045 }
......
...@@ -63,7 +63,7 @@ imap4d_test "SELECT en/to/tre"\ ...@@ -63,7 +63,7 @@ imap4d_test "SELECT en/to/tre"\
63 "OK \[READ-WRITE\] SELECT Completed" 63 "OK \[READ-WRITE\] SELECT Completed"
64 64
65 imap4d_test "FETCH 1 ALL"\ 65 imap4d_test "FETCH 1 ALL"\
66 "1 FETCH (FLAGS (\\Recent) INTERNALDATE \"25-Aug-2002 16:00:00 +0000\" RFC822.SIZE 285 ENVELOPE (\"Mon, 7 Feb 1994 21:52:25 -0800 (PST)\" \"afternoon meeting again\" ((\"Fred Foobar\" NIL \"foobar\" \"Blurdybloop.COM\")) ((\"Fred Foobar\" NIL \"foobar\" \"Blurdybloop.COM\")) ((\"Fred Foobar\" NIL \"foobar\" \"Blurdybloop.COM\")) ((NIL NIL \"mooch\" \"owatagu.siam.edu\")) NIL NIL NIL \"<B27397-0200000@Blurdybloop.COM>\"))"\ 66 -re {1 FETCH \(FLAGS \(\\Recent\) INTERNALDATE \"25-Aug-2002 16:00:00 [+-][0-9][0-9][0-9][0-9]\" RFC822.SIZE 285 ENVELOPE \(\"Mon, 7 Feb 1994 21:52:25 -0800 \(PST\)\" \"afternoon meeting again\" \(\(\"Fred Foobar\" NIL \"foobar\" \"Blurdybloop.COM\"\)\) \(\(\"Fred Foobar\" NIL \"foobar\" \"Blurdybloop.COM\"\)\) \(\(\"Fred Foobar\" NIL \"foobar\" \"Blurdybloop.COM\"\)\) \(\(NIL NIL \"mooch\" \"owatagu.siam.edu\"\)\) NIL NIL NIL \"<B27397-0200000@Blurdybloop.COM>\"\)\)}\
67 "OK" 67 "OK"
68 68
69 69
......
...@@ -47,7 +47,7 @@ imap4d_test "FETCH 3 (FLAGS)"\ ...@@ -47,7 +47,7 @@ imap4d_test "FETCH 3 (FLAGS)"\
47 47
48 # INTERNALDATE The internal date of the message. 48 # INTERNALDATE The internal date of the message.
49 imap4d_test "FETCH 3 INTERNALDATE"\ 49 imap4d_test "FETCH 3 INTERNALDATE"\
50 "3 FETCH (INTERNALDATE \"13-Jul-2002 00:43:18 +0000\")"\ 50 -re {3 FETCH \(INTERNALDATE \"13-Jul-2002 00:43:18 [+-][0-9][0-9][0-9][0-9]\"\)} \
51 "OK" 51 "OK"
52 52
53 # UID The unique identifier for the message. 53 # UID The unique identifier for the message.
...@@ -56,7 +56,7 @@ imap4d_test "FETCH 3 UID"\ ...@@ -56,7 +56,7 @@ imap4d_test "FETCH 3 UID"\
56 "OK" 56 "OK"
57 57
58 imap4d_test "FETCH 3 (FLAGS INTERNALDATE UID)"\ 58 imap4d_test "FETCH 3 (FLAGS INTERNALDATE UID)"\
59 "3 FETCH (FLAGS (\\Recent) INTERNALDATE \"13-Jul-2002 00:43:18 +0000\" UID 3)"\ 59 -re {3 FETCH \(FLAGS \(\\Recent\) INTERNALDATE \"13-Jul-2002 00:43:18 [+-][0-9][0-9][0-9][0-9]\" UID 3\)}\
60 "OK" 60 "OK"
61 61
62 # ENVELOPE The envelope structure of the message. This is 62 # ENVELOPE The envelope structure of the message. This is
...@@ -76,11 +76,11 @@ imap4d_test "FETCH 1:* ENVELOPE"\ ...@@ -76,11 +76,11 @@ imap4d_test "FETCH 1:* ENVELOPE"\
76 # RFC822.SIZE ENVELOPE) 76 # RFC822.SIZE ENVELOPE)
77 77
78 imap4d_test "FETCH 1:\* ALL"\ 78 imap4d_test "FETCH 1:\* ALL"\
79 "1 FETCH (FLAGS (\\Recent) INTERNALDATE \"28-Dec-2001 22:18:09 +0000\" RFC822.SIZE 1298 ENVELOPE (\"Fri, 28 Dec 2001 22:18:08 +0200\" \"Jabberwocky\" ((\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\")) ((\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\")) ((\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\")) ((\"Bar\" NIL \"bar\" \"dontmailme.org\")) NIL NIL NIL \"<200112282018.fBSKI8N04906@nonexistent.net>\"))"\ 79 -re {1 FETCH \(FLAGS \(\\Recent\) INTERNALDATE \"28-Dec-2001 22:18:09 [+-][0-9][0-9][0-9][0-9]\" RFC822.SIZE 1298 ENVELOPE \(\"Fri, 28 Dec 2001 22:18:08 \+0200\" \"Jabberwocky\" \(\(\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\"\)\) \(\(\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\"\)\) \(\(\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\"\)\) \(\(\"Bar\" NIL \"bar\" \"dontmailme.org\"\)\) NIL NIL NIL \"<200112282018.fBSKI8N04906@nonexistent.net>\"\)\)}\
80 "2 FETCH (FLAGS (\\Recent) INTERNALDATE \"28-Dec-2001 23:28:09 +0000\" RFC822.SIZE 547 ENVELOPE (\"Fri, 28 Dec 2001 23:28:08 +0200\" \"Re: Jabberwocky\" ((\"Bar\" NIL \"bar\" \"dontmailme.org\")) ((\"Bar\" NIL \"bar\" \"dontmailme.org\")) ((\"Bar\" NIL \"bar\" \"dontmailme.org\")) ((\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\")) NIL NIL NIL \"<200112232808.fERKR9N16790@dontmailme.org>\"))"\ 80 -re {2 FETCH \(FLAGS \(\\Recent\) INTERNALDATE \"28-Dec-2001 23:28:09 [+-][0-9][0-9][0-9][0-9]\" RFC822.SIZE 547 ENVELOPE \(\"Fri, 28 Dec 2001 23:28:08 \+0200\" \"Re: Jabberwocky\" \(\(\"Bar\" NIL \"bar\" \"dontmailme.org\"\)\) \(\(\"Bar\" NIL \"bar\" \"dontmailme.org\"\)\) \(\(\"Bar\" NIL \"bar\" \"dontmailme.org\"\)\) \(\(\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\"\)\) NIL NIL NIL \"<200112232808.fERKR9N16790@dontmailme.org>\"\)\)}\
81 "3 FETCH (FLAGS (\\Recent) INTERNALDATE \"13-Jul-2002 00:43:18 +0000\" RFC822.SIZE 1611 ENVELOPE (\"Sat, 13 Jul 2002 00:43:18 +0300\" \"Simple MIME\" ((\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\")) ((\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\")) ((\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\")) ((\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\")) NIL NIL NIL \"<200207122143.g6CLhIb05086@example.net>\"))"\ 81 -re {3 FETCH \(FLAGS \(\\Recent\) INTERNALDATE \"13-Jul-2002 00:43:18 [+-][0-9][0-9][0-9][0-9]\" RFC822.SIZE 1611 ENVELOPE \(\"Sat, 13 Jul 2002 00:43:18 \+0300\" \"Simple MIME\" \(\(\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\"\)\) \(\(\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\"\)\) \(\(\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\"\)\) \(\(\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\"\)\) NIL NIL NIL \"<200207122143.g6CLhIb05086@example.net>\"\)\)}\
82 "4 FETCH (FLAGS (\\Recent) INTERNALDATE \"13-Jul-2002 00:50:58 +0000\" RFC822.SIZE 3483 ENVELOPE (\"Sat, 13 Jul 2002 00:50:58 +0300\" \"Nested MIME\" ((\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\")) ((\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\")) ((\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\")) ((\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\")) NIL NIL NIL \"<200207122150.g6CLowb05126@example.net>\"))"\ 82 -re {4 FETCH \(FLAGS \(\\Recent\) INTERNALDATE \"13-Jul-2002 00:50:58 [+-][0-9][0-9][0-9][0-9]\" RFC822.SIZE 3483 ENVELOPE \(\"Sat, 13 Jul 2002 00:50:58 \+0300\" \"Nested MIME\" \(\(\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\"\)\) \(\(\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\"\)\) \(\(\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\"\)\) \(\(\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\"\)\) NIL NIL NIL \"<200207122150.g6CLowb05126@example.net>\"\)\)}\
83 "5 FETCH (FLAGS (\\Recent) INTERNALDATE \"13-Jul-2002 00:43:18 +0000\" RFC822.SIZE 884 ENVELOPE (\"Sat, 13 Jul 2002 00:43:18 +0300\" \"Empty MIME Parts\" ((\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\")) ((\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\")) ((\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\")) ((\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\")) NIL NIL NIL \"<200207122143.g6CLhIb05086@example.net>\"))"\ 83 -re {5 FETCH \(FLAGS \(\\Recent\) INTERNALDATE \"13-Jul-2002 00:43:18 [+-][0-9][0-9][0-9][0-9]\" RFC822.SIZE 884 ENVELOPE \(\"Sat, 13 Jul 2002 00:43:18 \+0300\" \"Empty MIME Parts\" \(\(\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\"\)\) \(\(\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\"\)\) \(\(\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\"\)\) \(\(\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\"\)\) NIL NIL NIL \"<200207122143.g6CLhIb05086@example.net>\"\)\)}\
84 "OK" 84 "OK"
85 85
86 # BODYSTRUCTURE The [MIME-IMB] body structure of the message. This 86 # BODYSTRUCTURE The [MIME-IMB] body structure of the message. This
...@@ -508,14 +508,14 @@ imap4d_test "FETCH 2 RFC822.TEXT"\ ...@@ -508,14 +508,14 @@ imap4d_test "FETCH 2 RFC822.TEXT"\
508 # RFC822.SIZE) 508 # RFC822.SIZE)
509 509
510 imap4d_test "FETCH 1 FAST" \ 510 imap4d_test "FETCH 1 FAST" \
511 "1 FETCH (FLAGS (\\Seen \\Recent) INTERNALDATE \"28-Dec-2001 22:18:09 +0000\" RFC822.SIZE 1298)"\ 511 -re {1 FETCH \(FLAGS \(\\Seen \\Recent\) INTERNALDATE \"28-Dec-2001 22:18:09 [+-][0-9][0-9][0-9][0-9]\" RFC822.SIZE 1298\)}\
512 "OK" 512 "OK"
513 513
514 # FULL Macro equivalent to: (FLAGS INTERNALDATE 514 # FULL Macro equivalent to: (FLAGS INTERNALDATE
515 # RFC822.SIZE ENVELOPE BODY) 515 # RFC822.SIZE ENVELOPE BODY)
516 516
517 imap4d_test "FETCH 4 FULL"\ 517 imap4d_test "FETCH 4 FULL"\
518 "4 FETCH (FLAGS (\\Recent) INTERNALDATE \"13-Jul-2002 00:50:58 +0000\" RFC822.SIZE 3483 ENVELOPE (\"Sat, 13 Jul 2002 00:50:58 +0300\" \"Nested MIME\" ((\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\")) ((\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\")) ((\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\")) ((\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\")) NIL NIL NIL \"<200207122150.g6CLowb05126@example.net>\") BODY ((\"text\" \"plain\" (\"name\" \"msg.21\" \"charset\" \"us-ascii\") \"<5122.1026510654.2@example.net>\" \"Father William Part I\" \"7BIT\" 351 10)((\"application\" \"octet-stream\" (\"name\" \"msg.22\") \"<5122.1026510654.4@example.net>\" \"Father William Part II\" \"base64\" 486)((\"application\" \"octet-stream\" (\"name\" \"msg.23\") \"<5122.1026510654.6@example.net>\" \"Father William Part III\" \"base64\" 490)(\"application\" \"octet-stream\" (\"name\" \"msg.24\") \"<5122.1026510654.7@example.net>\" \"Father William Part IV\" \"base64\" 502) \"mixed\" NIL NIL NIL) \"mixed\" NIL NIL NIL) \"mixed\" NIL NIL NIL))"\ 518 -re {4 FETCH \(FLAGS \(\\Recent\) INTERNALDATE \"13-Jul-2002 00:50:58 [+-][0-9][0-9][0-9][0-9]\" RFC822.SIZE 3483 ENVELOPE \(\"Sat, 13 Jul 2002 00:50:58 \+0300\" \"Nested MIME\" \(\(\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\"\)\) \(\(\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\"\)\) \(\(\"Sergey Poznyakoff\" NIL \"gray\" \"example.net\"\)\) \(\(\"Foo Bar\" NIL \"foobar\" \"nonexistent.net\"\)\) NIL NIL NIL \"<200207122150.g6CLowb05126@example.net>\"\) BODY \(\(\"text\" \"plain\" \(\"name\" \"msg.21\" \"charset\" \"us-ascii\"\) \"<5122.1026510654.2@example.net>\" \"Father William Part I\" \"7BIT\" 351 10\)\(\(\"application\" \"octet-stream\" \(\"name\" \"msg.22\"\) \"<5122.1026510654.4@example.net>\" \"Father William Part II\" \"base64\" 486\)\(\(\"application\" \"octet-stream\" \(\"name\" \"msg.23\"\) \"<5122.1026510654.6@example.net>\" \"Father William Part III\" \"base64\" 490\)\(\"application\" \"octet-stream\" \(\"name\" \"msg.24\"\) \"<5122.1026510654.7@example.net>\" \"Father William Part IV\" \"base64\" 502\) \"mixed\" NIL NIL NIL\) \"mixed\" NIL NIL NIL\) \"mixed\" NIL NIL NIL\)\)}\
519 "OK" 519 "OK"
520 520
521 imap4d_stop 521 imap4d_stop
......
...@@ -22,6 +22,7 @@ imap4d_auth "user!passwd" "guessme" ...@@ -22,6 +22,7 @@ imap4d_auth "user!passwd" "guessme"
22 imap4d_test -sort "LIST \"~\" \"*\""\ 22 imap4d_test -sort "LIST \"~\" \"*\""\
23 "LIST (\\NoInferiors) \"/\" ~/mbox1"\ 23 "LIST (\\NoInferiors) \"/\" ~/mbox1"\
24 "LIST (\\NoInferiors) \"/\" ~/mbox"\ 24 "LIST (\\NoInferiors) \"/\" ~/mbox"\
25 "LIST (\\NoInferiors) \"/\" ~/search.mbox"\
25 "LIST (\\NoInferiors) \"/\" ~/sieve.mbox"\ 26 "LIST (\\NoInferiors) \"/\" ~/sieve.mbox"\
26 "LIST (\\NoInferiors) \"/\" ~/teaparty.mbox"\ 27 "LIST (\\NoInferiors) \"/\" ~/teaparty.mbox"\
27 "LIST (\\NoInferiors) \"/\" ~/bigto.mbox"\ 28 "LIST (\\NoInferiors) \"/\" ~/bigto.mbox"\
...@@ -31,6 +32,7 @@ imap4d_test -sort "LIST \"~\" \"*\""\ ...@@ -31,6 +32,7 @@ imap4d_test -sort "LIST \"~\" \"*\""\
31 imap4d_test -sort "LIST \"~\" \"%\""\ 32 imap4d_test -sort "LIST \"~\" \"%\""\
32 "LIST (\\NoInferiors) \"/\" ~/mbox1"\ 33 "LIST (\\NoInferiors) \"/\" ~/mbox1"\
33 "LIST (\\NoInferiors) \"/\" ~/mbox"\ 34 "LIST (\\NoInferiors) \"/\" ~/mbox"\
35 "LIST (\\NoInferiors) \"/\" ~/search.mbox"\
34 "LIST (\\NoInferiors) \"/\" ~/sieve.mbox"\ 36 "LIST (\\NoInferiors) \"/\" ~/sieve.mbox"\
35 "LIST (\\NoInferiors) \"/\" ~/teaparty.mbox"\ 37 "LIST (\\NoInferiors) \"/\" ~/teaparty.mbox"\
36 "LIST (\\NoInferiors) \"/\" ~/bigto.mbox"\ 38 "LIST (\\NoInferiors) \"/\" ~/bigto.mbox"\
...@@ -41,6 +43,7 @@ imap4d_test -sort "LIST \"\" \"*\""\ ...@@ -41,6 +43,7 @@ imap4d_test -sort "LIST \"\" \"*\""\
41 "LIST (\\NoInferiors) NIL INBOX"\ 43 "LIST (\\NoInferiors) NIL INBOX"\
42 "LIST (\\NoInferiors) \"/\" mbox1"\ 44 "LIST (\\NoInferiors) \"/\" mbox1"\
43 "LIST (\\NoInferiors) \"/\" mbox"\ 45 "LIST (\\NoInferiors) \"/\" mbox"\
46 "LIST (\\NoInferiors) \"/\" search.mbox"\
44 "LIST (\\NoInferiors) \"/\" sieve.mbox"\ 47 "LIST (\\NoInferiors) \"/\" sieve.mbox"\
45 "LIST (\\NoInferiors) \"/\" teaparty.mbox"\ 48 "LIST (\\NoInferiors) \"/\" teaparty.mbox"\
46 "LIST (\\NoInferiors) \"/\" bigto.mbox"\ 49 "LIST (\\NoInferiors) \"/\" bigto.mbox"\
...@@ -60,6 +63,7 @@ imap4d_test -sort "LIST \"$MU_DATA_DIR\" \"*\""\ ...@@ -60,6 +63,7 @@ imap4d_test -sort "LIST \"$MU_DATA_DIR\" \"*\""\
60 "LIST (\\NoInferiors) \"/\" $MU_DATA_DIR/spool/relational.mbox" \ 63 "LIST (\\NoInferiors) \"/\" $MU_DATA_DIR/spool/relational.mbox" \
61 "LIST (\\NoInferiors) \"/\" $MU_DATA_DIR/spool/mbox1"\ 64 "LIST (\\NoInferiors) \"/\" $MU_DATA_DIR/spool/mbox1"\
62 "LIST (\\NoInferiors) \"/\" $MU_DATA_DIR/spool/mbox"\ 65 "LIST (\\NoInferiors) \"/\" $MU_DATA_DIR/spool/mbox"\
66 "LIST (\\NoInferiors) \"/\" $MU_DATA_DIR/spool/search.mbox"\
63 "LIST (\\NoInferiors) \"/\" $MU_DATA_DIR/spool/sieve.mbox"\ 67 "LIST (\\NoInferiors) \"/\" $MU_DATA_DIR/spool/sieve.mbox"\
64 "LIST (\\NoInferiors) \"/\" $MU_DATA_DIR/spool/teaparty.mbox"\ 68 "LIST (\\NoInferiors) \"/\" $MU_DATA_DIR/spool/teaparty.mbox"\
65 "LIST (\\NoSelect) \"/\" $MU_DATA_DIR/folder"\ 69 "LIST (\\NoSelect) \"/\" $MU_DATA_DIR/folder"\
......
...@@ -30,15 +30,15 @@ ...@@ -30,15 +30,15 @@
30 # contains a listing of message sequence numbers corresponding to 30 # contains a listing of message sequence numbers corresponding to
31 # those messages that match the searching criteria. 31 # those messages that match the searching criteria.
32 32
33 imap4d_start 33 imap4d_start -mbox "search.mbox"
34 imap4d_auth "user!passwd" "guessme" 34 imap4d_auth "user!passwd" "guessme"
35 35
36 imap4d_test "SELECT INBOX"\ 36 imap4d_test "SELECT INBOX"\
37 "95 EXISTS"\ 37 "8 EXISTS"\
38 "95 RECENT"\ 38 "5 RECENT"\
39 -re {OK \[UIDVALIDITY [0-9]+\] UID valididy status}\ 39 -re {OK \[UIDVALIDITY [0-9]+\] UID valididy status}\
40 "OK \[UIDNEXT 96\] Predicted next uid"\ 40 "OK \[UIDNEXT 9\] Predicted next uid"\
41 "OK \[UNSEEN 1\] first unseen messsage "\ 41 "OK \[UNSEEN 4\] first unseen messsage "\
42 "FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)"\ 42 "FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)"\
43 "OK \[PERMANENTFLAGS (\\Answered \\Deleted \\Seen)\] Permanent flags"\ 43 "OK \[PERMANENTFLAGS (\\Answered \\Deleted \\Seen)\] Permanent flags"\
44 "OK \[READ-WRITE\] SELECT Completed" 44 "OK \[READ-WRITE\] SELECT Completed"
...@@ -48,14 +48,14 @@ imap4d_test "SELECT INBOX"\ ...@@ -48,14 +48,14 @@ imap4d_test "SELECT INBOX"\
48 # number set 48 # number set
49 49
50 imap4d_test "SEARCH 1:*" \ 50 imap4d_test "SEARCH 1:*" \
51 "SEARCH 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95" \ 51 "SEARCH 1 2 3 4 5 6 7 8" \
52 "OK" 52 "OK"
53 53
54 # ALL All messages in the mailbox; the default initial 54 # ALL All messages in the mailbox; the default initial
55 # key for ANDing. 55 # key for ANDing.
56 56
57 imap4d_test "SEARCH ALL" \ 57 imap4d_test "SEARCH ALL" \
58 "SEARCH 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95" \ 58 "SEARCH 1 2 3 4 5 6 7 8" \
59 "OK" 59 "OK"
60 60
61 # NEW Messages that have the \Recent flag set but not the 61 # NEW Messages that have the \Recent flag set but not the
...@@ -64,39 +64,39 @@ imap4d_test "SEARCH ALL" \ ...@@ -64,39 +64,39 @@ imap4d_test "SEARCH ALL" \
64 64
65 # All messages are still new 65 # All messages are still new
66 imap4d_test "SEARCH NEW" \ 66 imap4d_test "SEARCH NEW" \
67 "SEARCH 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95" \ 67 "SEARCH 4 5 6 7 8" \
68 "OK" 68 "OK"
69 69
70 # FROM <string> Messages that contain the specified string in the 70 # FROM <string> Messages that contain the specified string in the
71 # envelope structure's FROM field. 71 # envelope structure's FROM field.
72 72
73 imap4d_test "SEARCH FROM alice" \ 73 imap4d_test "SEARCH FROM corrector" \
74 "SEARCH 2 4 6 8 10 12 14 20 25 27 29 33 36 38 40 43 45 47 51 53 55 57 59 63 66 68 70 72 74 76 78 80 82 85 87 90 93 95" \ 74 "SEARCH 2 4 8" \
75 "OK" 75 "OK"
76 76
77 imap4d_test "SEARCH FROM hare" \ 77 imap4d_test "SEARCH FROM lexi@example.net" \
78 "SEARCH 1 3 5 7 9 11 13 16 22 24 35 42 58 62 71" \ 78 "SEARCH 1 3 5 6 7" \
79 "OK" 79 "OK"
80 80
81 # LARGER <n> Messages with an [RFC-822] size larger than the 81 # LARGER <n> Messages with an [RFC-822] size larger than the
82 # specified number of octets. 82 # specified number of octets.
83 83
84 imap4d_test "SEARCH LARGER 512" \ 84 imap4d_test "SEARCH LARGER 512" \
85 "SEARCH 41 46" \ 85 "SEARCH 3 4" \
86 "OK" 86 "OK"
87 87
88 # SMALLER <n> Messages with an [RFC-822] size smaller than the 88 # SMALLER <n> Messages with an [RFC-822] size smaller than the
89 # specified number of octets. 89 # specified number of octets.
90 90
91 imap4d_test "SEARCH SMALLER 300" \ 91 imap4d_test "SEARCH SMALLER 400" \
92 "SEARCH 12 20 35" \ 92 "SEARCH 7 8" \
93 "OK" 93 "OK"
94 94
95 # SUBJECT <string> Messages that contain the specified string in the 95 # SUBJECT <string> Messages that contain the specified string in the
96 # envelope structure's SUBJECT field. 96 # envelope structure's SUBJECT field.
97 97
98 imap4d_test "SEARCH SUBJECT \"watch\"" \ 98 imap4d_test "SEARCH SUBJECT \"Alliance\"" \
99 "SEARCH 19 20 21 22 23 24 25 26 27 28 29"\ 99 "SEARCH 6"\
100 "OK" 100 "OK"
101 101
102 # HEADER <field-name> <string> 102 # HEADER <field-name> <string>
...@@ -105,75 +105,65 @@ imap4d_test "SEARCH SUBJECT \"watch\"" \ ...@@ -105,75 +105,65 @@ imap4d_test "SEARCH SUBJECT \"watch\"" \
105 # contains the specified string in the [RFC-822] 105 # contains the specified string in the [RFC-822]
106 # field-body. 106 # field-body.
107 107
108 imap4d_test "SEARCH HEADER Message-Id \"<200207292200.3303@wonder.land>\"" \ 108 imap4d_test "SEARCH HEADER Message-Id \"<200207291200.3303@example.org>\"" \
109 "SEARCH 3" \ 109 "SEARCH 3" \
110 "OK" 110 "OK"
111 111
112 # CC <string> Messages that contain the specified string in the 112 # CC <string> Messages that contain the specified string in the
113 # envelope structure's CC field. 113 # envelope structure's CC field.
114 114
115 imap4d_test "SEARCH CC dormouse" \ 115 imap4d_test "SEARCH CC Corrector" \
116 "SEARCH 60" \ 116 "SEARCH 6" \
117 "OK" 117 "OK"
118 118
119 # TO <string> Messages that contain the specified string in the 119 # TO <string> Messages that contain the specified string in the
120 # envelope structure's TO field. 120 # envelope structure's TO field.
121 121
122 imap4d_test "SEARCH TO hare"\ 122 imap4d_test "SEARCH TO editor+recheck"\
123 "SEARCH 2 4 6 8 10 12 14 21 23 42 59 72" \ 123 "SEARCH 7" \
124 "OK" 124 "OK"
125 125
126 # SENTBEFORE <date> 126 # SENTBEFORE <date>
127 # Messages whose [RFC-822] Date: header is earlier 127 # Messages whose [RFC-822] Date: header is earlier
128 # than the specified date. 128 # than the specified date.
129 129
130 imap4d_test "SEARCH SENTBEFORE \"29-Jul-2002 22:00:02 +0100\"" \ 130 imap4d_test "SEARCH SENTBEFORE \"30-Jul-2002\"" \
131 "SEARCH 1"\ 131 "SEARCH 1 2"\
132 "OK" 132 "OK"
133 133
134 # SENTSINCE <date> 134 # SENTSINCE <date>
135 # Messages whose [RFC-822] Date: header is within or 135 # Messages whose [RFC-822] Date: header is within or
136 # later than the specified date. 136 # later than the specified date.
137 137
138 imap4d_test "SEARCH SENTSINCE \"29-Jul-2002 22:01:32 +0100\""\ 138 imap4d_test "SEARCH SENTSINCE \"31-Jul-2002\""\
139 "SEARCH 92 93 94 95"\ 139 "SEARCH 5 6 7 8"\
140 "OK"
141
142 imap4d_test "SEARCH SENTSINCE \"29-Jul-2002 23:01:32 +0200\""\
143 "SEARCH 92 93 94 95"\
144 "OK" 140 "OK"
145 141
146 # BEFORE <date> Messages whose internal date is earlier than the 142 # BEFORE <date> Messages whose internal date is earlier than the
147 # specified date. 143 # specified date.
148 144
149 imap4d_test "SEARCH BEFORE \"29-Jul-2002 22:00:09 +0000\""\ 145 imap4d_test "SEARCH BEFORE \"30-Jul-2002\""\
150 "SEARCH 1"\ 146 "SEARCH 1"\
151 "OK" 147 "OK"
152 148
153 # SINCE <date> Messages whose internal date is within or later 149 # SINCE <date> Messages whose internal date is within or later
154 # than the specified date. 150 # than the specified date.
155 151
156 imap4d_test "SEARCH SINCE \"29-Jul-2002 22:01:36 +0000\""\ 152 imap4d_test "SEARCH SINCE \"30-Jul-2002\""\
157 "SEARCH 89 90 91 92 93 94 95"\ 153 "SEARCH 2 3 4 5 6 7 8"\
158 "OK"
159
160 imap4d_test "STORE 3,5,89 +FLAGS (\\Answered)"\
161 "3 FETCH (FLAGS (\\Answered \\Recent))"\
162 "5 FETCH (FLAGS (\\Answered \\Recent))"\
163 "89 FETCH (FLAGS (\\Answered \\Recent))"\
164 "OK" 154 "OK"
165 155
166 # ANSWERED Messages with the \Answered flag set. 156 # ANSWERED Messages with the \Answered flag set.
167 157
168 imap4d_test "SEARCH ANSWERED"\ 158 imap4d_test "SEARCH ANSWERED"\
169 "SEARCH 3 5 89"\ 159 "SEARCH 2 3"\
170 "OK" 160 "OK"
171 161
172 # TEXT <string> Messages that contain the specified string in the 162 # TEXT <string> Messages that contain the specified string in the
173 # header or body of the message. 163 # header or body of the message.
174 164
175 imap4d_test "SEARCH TEXT wine"\ 165 imap4d_test "SEARCH TEXT person"\
176 "SEARCH 1 2"\ 166 "SEARCH 2 5 8"\
177 "OK" 167 "OK"
178 168
179 ## Boolean operations 169 ## Boolean operations
...@@ -181,33 +171,33 @@ imap4d_test "SEARCH TEXT wine"\ ...@@ -181,33 +171,33 @@ imap4d_test "SEARCH TEXT wine"\
181 # When multiple keys are specified, the result is the intersection 171 # When multiple keys are specified, the result is the intersection
182 # (AND function) of all the messages that match those keys. 172 # (AND function) of all the messages that match those keys.
183 173
184 imap4d_test "SEARCH TEXT wine FROM alice"\ 174 imap4d_test "SEARCH TEXT person FROM corrector"\
185 "SEARCH 2"\ 175 "SEARCH 2"\
186 "OK" 176 "OK"
187 177
178 imap4d_test "SEARCH SENTSINCE \"30-Jul-2002\" SENTBEFORE \"31-Jul-2002\"" \
179 "SEARCH 3 4" \
180 "OK"
181
188 # OR <search-key1> <search-key2> 182 # OR <search-key1> <search-key2>
189 # Messages that match either search key. 183 # Messages that match either search key.
190 184
191 imap4d_test "SEARCH OR FROM alice ANSWERED"\ 185 imap4d_test "SEARCH OR FROM corrector ANSWERED"\
192 "SEARCH 2 3 4 5 6 8 10 12 14 20 25 27 29 33 36 38 40 43 45 47 51 53 55 57 59 63 66 68 70 72 74 76 78 80 82 85 87 89 90 93 95"\ 186 "SEARCH 2 3 4 8" \
193 "OK" 187 "OK"
194 188
195 ## Check precedence 189 ## Check precedence
196 190
197 imap4d_test "SEARCH (OR FROM alice ANSWERED) SENTSINCE \"29-Jul-2002 22:00:33 +0100\""\ 191 imap4d_test "SEARCH (OR FROM corrector ANSWERED) SENTSINCE \"30-Jul-2002\""\
198 "SEARCH 33 36 38 40 43 45 47 51 53 55 57 59 63 66 68 70 72 74 76 78 80 82 85 87 89 90 93 95" \ 192 "SEARCH 3 4 8" \
199 "OK"
200
201 imap4d_test "SEARCH (OR FROM alice ANSWERED) SENTSINCE \"29-Jul-2002 22:00:33 +0100\" SENTBEFORE \"29-Jul-2002 22:00:56 +0100\""\
202 "SEARCH 33 36 38 40 43 45 47 51 53 55"\
203 "OK" 193 "OK"
204 194
205 imap4d_test "SEARCH OR FROM alice ANSWERED SENTSINCE \"29-Jul-2002 22:00:33 +0100\" SENTBEFORE \"29-Jul-2002 22:00:56 +0100\""\ 195 imap4d_test "SEARCH OR FROM corrector ANSWERED SENTSINCE \"30-Jul-2002\""\
206 "SEARCH 33 36 38 40 43 45 47 51 53 55"\ 196 "SEARCH 3 4 8" \
207 "OK" 197 "OK"
208 198
209 imap4d_test "SEARCH OR FROM alice (ANSWERED SENTSINCE \"29-Jul-2002 22:00:33 +0100\" SENTBEFORE \"29-Jul-2002 22:00:56 +0100\")"\ 199 imap4d_test "SEARCH OR FROM corrector (ANSWERED SENTSINCE \"30-Jul-2002\")"\
210 "SEARCH 2 4 6 8 10 12 14 20 25 27 29 33 36 38 40 43 45 47 51 53 55 57 59 63 66 68 70 72 74 76 78 80 82 85 87 90 93 95"\ 200 "SEARCH 2 3 4 8" \
211 "OK" 201 "OK"
212 202
213 imap4d_stop 203 imap4d_stop
......
...@@ -107,10 +107,15 @@ proc imap4d_start {args} { ...@@ -107,10 +107,15 @@ proc imap4d_start {args} {
107 verbose "Starting imap4d" 107 verbose "Starting imap4d"
108 108
109 set reuse_spool 0 109 set reuse_spool 0
110 set mbox "teaparty.mbox"
111
110 for {set i 0} {$i < [llength $args]} {incr i} { 112 for {set i 0} {$i < [llength $args]} {incr i} {
111 set a [lindex $args $i] 113 set a [lindex $args $i]
112 if {"$a" == "-reuse-spool"} { 114 if {"$a" == "-reuse-spool"} {
113 set reuse_spool 1 115 set reuse_spool 1
116 } elseif {"$a" == "-mbox"} {
117 set mbox [lindex $args [expr $i + 1]]
118 incr i
114 } else { 119 } else {
115 break; 120 break;
116 } 121 }
...@@ -118,7 +123,7 @@ proc imap4d_start {args} { ...@@ -118,7 +123,7 @@ proc imap4d_start {args} {
118 123
119 if {$reuse_spool == 0} { 124 if {$reuse_spool == 0} {
120 mu_prepare_spools 125 mu_prepare_spools
121 mu_copy_file $MU_SPOOL_DIR/teaparty.mbox $MU_SPOOL_DIR/INBOX 126 mu_copy_file $MU_SPOOL_DIR/$mbox $MU_SPOOL_DIR/INBOX
122 } 127 }
123 return [default_imap4d_start [concat [lrange $args $i end]]] 128 return [default_imap4d_start [concat [lrange $args $i end]]]
124 } 129 }
......
...@@ -335,8 +335,40 @@ add2set (size_t ** set, int *n, unsigned long val) ...@@ -335,8 +335,40 @@ add2set (size_t ** set, int *n, unsigned long val)
335 return 0; 335 return 0;
336 } 336 }
337 337
338 static void
339 adjust_tm (struct tm *tm, mu_timezone *tz, enum datetime_parse_mode flag)
340 {
341 switch (flag)
342 {
343 case datetime_default:
344 break;
345 case datetime_date_only:
346 tm->tm_sec = 0;
347 tm->tm_min = 0;
348 tm->tm_hour = 0;
349 #if HAVE_STRUCT_TM_TM_ISDST
350 tm->tm_isdst = 0;
351 #endif
352 #if HAVE_STRUCT_TM_TM_GMTOFF
353 tm->tm_gmtoff = 0;
354 #endif
355 tz->utc_offset = 0;
356 tz->tz_name = NULL;
357 break;
358
359 case datetime_time_only:
360 tm->tm_mon = 0;
361 tm->tm_year = 0;
362 tm->tm_yday = 0;
363 tm->tm_wday = 0;
364 tm->tm_mday = 0;
365 break;
366 }
367 }
368
338 int 369 int
339 util_parse_internal_date (char *date, time_t * timep) 370 util_parse_internal_date (char *date, time_t *timep,
371 enum datetime_parse_mode flag)
340 { 372 {
341 struct tm tm; 373 struct tm tm;
342 mu_timezone tz; 374 mu_timezone tz;
...@@ -346,6 +378,8 @@ util_parse_internal_date (char *date, time_t * timep) ...@@ -346,6 +378,8 @@ util_parse_internal_date (char *date, time_t * timep)
346 if (mu_parse_imap_date_time ((const char **) datep, &tm, &tz)) 378 if (mu_parse_imap_date_time ((const char **) datep, &tm, &tz))
347 return 1; 379 return 1;
348 380
381 adjust_tm (&tm, &tz, flag);
382
349 time = mu_tm2time (&tm, &tz); 383 time = mu_tm2time (&tm, &tz);
350 if (time == (time_t) - 1) 384 if (time == (time_t) - 1)
351 return 2; 385 return 2;
...@@ -355,7 +389,8 @@ util_parse_internal_date (char *date, time_t * timep) ...@@ -355,7 +389,8 @@ util_parse_internal_date (char *date, time_t * timep)
355 } 389 }
356 390
357 int 391 int
358 util_parse_822_date (const char *date, time_t * timep) 392 util_parse_822_date (const char *date, time_t *timep,
393 enum datetime_parse_mode flag)
359 { 394 {
360 struct tm tm; 395 struct tm tm;
361 mu_timezone tz; 396 mu_timezone tz;
...@@ -363,6 +398,7 @@ util_parse_822_date (const char *date, time_t * timep) ...@@ -363,6 +398,7 @@ util_parse_822_date (const char *date, time_t * timep)
363 398
364 if (mu_parse822_date_time (&p, date + strlen (date), &tm, &tz) == 0) 399 if (mu_parse822_date_time (&p, date + strlen (date), &tm, &tz) == 0)
365 { 400 {
401 adjust_tm (&tm, &tz, flag);
366 *timep = mu_tm2time (&tm, &tz); 402 *timep = mu_tm2time (&tm, &tz);
367 return 0; 403 return 0;
368 } 404 }
...@@ -370,13 +406,15 @@ util_parse_822_date (const char *date, time_t * timep) ...@@ -370,13 +406,15 @@ util_parse_822_date (const char *date, time_t * timep)
370 } 406 }
371 407
372 int 408 int
373 util_parse_ctime_date (const char *date, time_t * timep) 409 util_parse_ctime_date (const char *date, time_t *timep,
410 enum datetime_parse_mode flag)
374 { 411 {
375 struct tm tm; 412 struct tm tm;
376 mu_timezone tz; 413 mu_timezone tz;
377 414
378 if (mu_parse_ctime_date_time (&date, &tm, &tz) == 0) 415 if (mu_parse_ctime_date_time (&date, &tm, &tz) == 0)
379 { 416 {
417 adjust_tm (&tm, &tz, flag);
380 *timep = mu_tm2time (&tm, &tz); 418 *timep = mu_tm2time (&tm, &tz);
381 return 0; 419 return 0;
382 } 420 }
......
...@@ -182,7 +182,7 @@ mu_parse_imap_date_time (const char **p, struct tm *tm, mu_timezone *tz) ...@@ -182,7 +182,7 @@ mu_parse_imap_date_time (const char **p, struct tm *tm, mu_timezone *tz)
182 182
183 /* "ctime" format is: Thu Jul 01 15:58:27 1999, with no trailing \n. */ 183 /* "ctime" format is: Thu Jul 01 15:58:27 1999, with no trailing \n. */
184 int 184 int
185 mu_parse_ctime_date_time (const char **p, struct tm *tm, mu_timezone * tz) 185 mu_parse_ctime_date_time (const char **p, struct tm *tm, mu_timezone *tz)
186 { 186 {
187 int wday = 0; 187 int wday = 0;
188 int year = 0; 188 int year = 0;
...@@ -236,9 +236,12 @@ mu_parse_ctime_date_time (const char **p, struct tm *tm, mu_timezone * tz) ...@@ -236,9 +236,12 @@ mu_parse_ctime_date_time (const char **p, struct tm *tm, mu_timezone * tz)
236 #endif 236 #endif
237 } 237 }
238 238
239 /* ctime has no timezone information, set tz to UTC if they ask. */ 239 /* ctime has no timezone information, set tz to local TZ if they ask. */
240 if (tz) 240 if (tz)
241 memset (tz, 0, sizeof (struct mu_timezone)); 241 {
242 tz->utc_offset = mu_utc_offset ();
243 tz->tz_name = NULL;
244 }
242 245
243 return 0; 246 return 0;
244 } 247 }
......
...@@ -45,7 +45,7 @@ proc mu_copy_file {src dst} { ...@@ -45,7 +45,7 @@ proc mu_copy_file {src dst} {
45 set output [open $dst w] 45 set output [open $dst w]
46 set arg "$" 46 set arg "$"
47 for {gets $input line} {![eof $input]} {gets $input line} { 47 for {gets $input line} {![eof $input]} {gets $input line} {
48 puts $output [subst -nobackslashes $line] 48 puts $output [subst -nobackslashes -nocommands $line]
49 } 49 }
50 close $input 50 close $input
51 close $output 51 close $output
......
1 bigto.mbox 1 bigto.mbox
2 mbox1 2 mbox1
3 mbox 3 mbox
4 search.mbox
4 sieve.mbox 5 sieve.mbox
5 relational.mbox 6 relational.mbox
6 teaparty.mbox 7 teaparty.mbox
......
1 From lexi@example.net Mon Jul 29 22:00:08 2002
2 Received: (from lexi@example.com)
3 by example.org id 3301
4 for editor@example.org; Mon, 29 Jul 2002 22:00:06 +0100
5 Date: Mon, 29 Jul 2002 22:00:01 +0100
6 From: Lexicographer <lexi@example.com>
7 To: Editor <editor@example.org>
8 Subject: Abasement
9 Status: OR
10
11 ABASEMENT, n. A decent and customary mental attitude in the presence
12 of wealth of power. Peculiarly appropriate in an employee when
13 addressing an employer.
14
15 From correct@example.net Tue Jul 30 00:00:00 2002
16 Received: (from correct@example.com)
17 by example.org id 3302
18 for editor@example.org Tue, Jul 30 00:00:00 2002 +0100
19 Date: Mon, 29 Jul 2002 22:00:02 +0100
20 From: Corrector <correct@example.com>
21 To: Editor <editor@example.org>
22 Subject: Aboriginies
23 Status: ORA
24
25 ABORIGINIES, n. Persons of little worth found cumbering the soil of a
26 newly discovered country. They soon cease to cumber; they fertilize.
27
28 From lexi@example.net Tue Jul 30 12:00:10 2002
29 Received: (from lexi@example.com)
30 by example.org id 3303
31 for editor@example.org Tue, 30 Jul 2002 12:00:08 +0100
32 Date: Tue, 30 Jul 2002 12:00:03 +0100
33 From: Lexicographer <lexi@example.com>
34 To: Editor <editor@example.org>
35 Message-Id: "<200207291200.3303@example.org>"
36 Subject: Abnormal
37 Status: ORA
38
39 ABNORMAL, adj. Not conforming to standard. In matters of thought and
40 conduct, to be independent is to be abnormal, to be abnormal is to be
41 detested. Wherefore the lexicographer adviseth a striving toward the
42 straiter [sic] resemblance of the Average Man than he hath to himself.
43 Whoso attaineth thereto shall have peace, the prospect of death and
44 the hope of Hell.
45
46 From corrector@example.net Tue Jul 30 12:00:11 2002
47 Received: (from correct@example.com)
48 by example.org id 3304
49 for editor@example.org Tue, 30 Jul 2002 12:00:09 +0100
50 Date: Tue, 30 Jul 2002 12:00:04 +0100
51 From: Corrector <corrector@example.com>
52 To: Editor <editor@example.org>
53 Subject: Occident
54
55 OCCIDENT, n. The part of the world lying west (or east) of the
56 Orient. It is largely inhabited by Christians, a powerful subtribe of
57 the Hypocrites, whose principal industries are murder and cheating,
58 which they are pleased to call "war" and "commerce." These, also, are
59 the principal industries of the Orient.
60
61 From lexi@example.net Wed Jul 31 02:00:12 2002
62 Received: (from lexi@example.com)
63 by example.org id 3305
64 for corrector@example.org Wed, 31 Jul 2002 02:00:10 +0100
65 Date: Wed, 31 Jul 2002 02:00:05 +0100
66 From: Lexicographer <lexi@example.com>
67 To: Corrector <correct@example.org>
68 Subject: Acquaintance
69
70 ACQUAINTANCE, n. A person whom we know well enough to borrow from,
71 but not well enough to lend to. A degree of friendship called slight
72 when its object is poor or obscure, and intimate when he is rich or
73 famous.
74
75 From lexi@example.net Thu Aug 01 10:00:13 2002
76 Received: (from lexi@example.com)
77 by example.org id 3306
78 for editor@example.org Thu, 01 Aug 2002 10:00:11 +0100
79 Date: Thu, 01 Aug 2002 22:00:06 +0100
80 From: Lexicographer <lexi@example.com>
81 To: Editor <editor@example.org>
82 Cc: Corrector <correct@example.org>
83 Subject: Alliance
84
85 ALLIANCE, n. In international politics, the union of two thieves who
86 have their hands so deeply inserted in each other's pockets that they
87 cannot separately plunder a third.
88
89 From lexi@example.net Fri Aug 02 11:00:14 2002
90 Received: (from lexi@example.com)
91 by example.org id 3307
92 for editor@example.org Fri, 02 Aug 2002 11:00:12 +0100
93 Date: Fri, 02 Aug 2002 11:00:07 +0100
94 From: Lexicographer <lexi@example.com>
95 To: Editor <editor+recheck@example.org>
96 Subject: White
97
98 WHITE, adj. and n. Black.
99
100 From correct@example.net Fri Aug 02 12:00:15 2002
101 Received: (from correct@example.com)
102 by example.org id 3308
103 for editor@example.org Fri, 02 Aug 2002 12:00:13 +0100
104 Date: Fri, 02 Aug 2002 12:00:08 +0100
105 From: Corrector <correct@example.com>
106 To: Editor <editor@example.org>
107 Subject: Telephone
108
109 TELEPHONE, n. An invention of the devil which abrogates some of the
110 advantages of making a disagreeable person keep his distance.
111
112
113