]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Fix doveadm search query parsing to use timezones correctly.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 4 Nov 2016 10:04:11 +0000 (12:04 +0200)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 4 Nov 2016 10:57:34 +0000 (12:57 +0200)
When using a date string, e.g. "senton 25-Mar-2007" it should work the same
way as IMAP does and show all mails whose sent date is on 25th, ignoring
whatever the timezone is in the Date header (or in case of received/saved-date
it would be using the timestamps in server's local timezone, again just like
IMAP).

When search with an exact UNIX timestamp or a time interval (e.g.
"3 days"), it should be using UTC times for doing all comparisons.

src/doveadm/doveadm-dsync.c
src/lib-storage/mail-search-register-human.c
src/lib-storage/mail-storage.c
src/lib-storage/mail-storage.h

index fe144877c4cfc063c354791dc1eae07327795778..343d97548e85aaae9742eb7c270c33272dfbdf09 100644 (file)
@@ -969,6 +969,7 @@ cmd_mailbox_dsync_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
 {
        struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx;
        const char *str, *error;
+       bool utc;
 
        switch (c) {
        case '1':
@@ -1048,11 +1049,11 @@ cmd_mailbox_dsync_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
                ctx->state_input = optarg;
                break;
        case 't':
-               if (mail_parse_human_timestamp(optarg, &ctx->sync_since_timestamp) < 0)
+               if (mail_parse_human_timestamp(optarg, &ctx->sync_since_timestamp, &utc) < 0)
                        i_fatal("Invalid -t parameter: %s", optarg);
                break;
        case 'e':
-               if (mail_parse_human_timestamp(optarg, &ctx->sync_until_timestamp) < 0)
+               if (mail_parse_human_timestamp(optarg, &ctx->sync_until_timestamp, &utc) < 0)
                        i_fatal("Invalid -e parameter: %s", optarg);
                break;
        case 'I':
index f192fe2ae7faa69c8cad0af31ee7616b24b75556..7379e8e4ba4e8e02bff163e7f4b2776a6314ad5d 100644 (file)
@@ -35,15 +35,16 @@ arg_new_human_date(struct mail_search_build_context *ctx,
 {
        struct mail_search_arg *sarg;
        const char *value;
+       bool utc;
 
        sarg = mail_search_build_new(ctx, type);
        if (mail_search_parse_string(ctx->parser, &value) < 0)
                return NULL;
 
-       if (mail_parse_human_timestamp(value, &sarg->value.time) < 0)
+       if (mail_parse_human_timestamp(value, &sarg->value.time, &utc) < 0)
                sarg->value.time = (time_t)-1;
-
-       sarg->value.search_flags = MAIL_SEARCH_ARG_FLAG_USE_TZ;
+       if (utc)
+               sarg->value.search_flags = MAIL_SEARCH_ARG_FLAG_USE_TZ;
 
        if (sarg->value.time == (time_t)-1) {
                ctx->_error = p_strconcat(ctx->pool,
index 91ef088fd2aa62db71968e774fb30fccb3147886..87cb8b75ff9b1fa07dd28b6c68f91ecbdfde4079 100644 (file)
@@ -2525,7 +2525,8 @@ mail_storage_settings_to_index_flags(const struct mail_storage_settings *set)
        return index_flags;
 }
 
-int mail_parse_human_timestamp(const char *str, time_t *timestamp_r)
+int mail_parse_human_timestamp(const char *str, time_t *timestamp_r,
+                              bool *utc_r)
 {
        struct tm tm;
        unsigned int secs;
@@ -2542,15 +2543,19 @@ int mail_parse_human_timestamp(const char *str, time_t *timestamp_r)
                tm.tm_mon = (str[5]-'0') * 10 + (str[6]-'0') - 1;
                tm.tm_mday = (str[8]-'0') * 10 + (str[9]-'0');
                *timestamp_r = mktime(&tm);
+               *utc_r = FALSE;
                return 0;
        } else if (imap_parse_date(str, timestamp_r)) {
                /* imap date */
+               *utc_r = FALSE;
                return 0;
        } else if (str_to_time(str, timestamp_r) == 0) {
                /* unix timestamp */
+               *utc_r = TRUE;
                return 0;
        } else if (settings_get_time(str, &secs, &error) == 0) {
                *timestamp_r = ioloop_time - secs;
+               *utc_r = TRUE;
                return 0;
        } else {
                return -1;
index f5c2dbaaefecb42197d2c50113ed689c22b29f7e..6738cbc330eb32755874eacba5f534f5191a428a 100644 (file)
@@ -918,9 +918,16 @@ void mail_set_cache_corrupted(struct mail *mail,
    128 bits are returned. */
 void mail_generate_guid_128_hash(const char *guid, guid_128_t guid_128_r);
 
-/* Parse a human-writable string into a timestamp. Returns 0 and timestamp on
-   success, -1 if the string couldn't be parsed. Currently supported string
-   formats: yyyy-mm-dd, imap date, unix timestamp, interval (e.g. n days). */
-int mail_parse_human_timestamp(const char *str, time_t *timestamp_r);
+/* Parse a human-writable string into a timestamp. utc_r controls whether
+   the returned timestamp should be treated as an exact UTC time (TRUE), or
+   whether this is a human-given date where the timestamp could be adjusted
+   by the matched mails' timezones (see MAIL_SEARCH_ARG_FLAG_USE_TZ).
+
+   Returns 0 and timestamp on success, -1 if the string couldn't be parsed.
+   Currently supported string formats: yyyy-mm-dd (utc=FALSE),
+   imap date (utc=FALSE), unix timestamp (utc=TRUE), interval (e.g. n days,
+   utc=TRUE). */
+int mail_parse_human_timestamp(const char *str, time_t *timestamp_r,
+                              bool *utc_r);
 
 #endif