]> 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>
Wed, 9 Nov 2016 12:40:28 +0000 (14:40 +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 a0db38d53c03d47fd45ef1b04bad9a406a9c62ab..48648db17c761b5fa053acdb2ff1e938ba366f64 100644 (file)
@@ -964,6 +964,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':
@@ -1043,11 +1044,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 8a6b6afcc1ee8f178b8785a325a58d1db62ec9b2..151ef477b092cd65ec10716548c29e24b4ae9d25 100644 (file)
@@ -2524,7 +2524,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;
@@ -2541,15 +2542,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 b13fce5d53b254be6db3001465b60280a97fd725..db089580b74fcbf3d92108f948f81c0350aee6ce 100644 (file)
@@ -923,9 +923,16 @@ void mail_set_cache_corrupted_reason(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