From: Stephan Bosch Date: Thu, 19 Mar 2020 16:14:34 +0000 (+0100) Subject: lib-storage: index: imapc: Implement support for SAVEDATE attribute. X-Git-Tag: 2.3.11.2~484 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2c29e3c0e057ce284eee43b635e225557ac79571;p=thirdparty%2Fdovecot%2Fcore.git lib-storage: index: imapc: Implement support for SAVEDATE attribute. --- diff --git a/src/lib-storage/index/imapc/imapc-mail-fetch.c b/src/lib-storage/index/imapc/imapc-mail-fetch.c index 9e8bd41fca..1f93d4b5d1 100644 --- a/src/lib-storage/index/imapc/imapc-mail-fetch.c +++ b/src/lib-storage/index/imapc/imapc-mail-fetch.c @@ -253,6 +253,11 @@ imapc_mail_send_fetch(struct mail *_mail, enum mail_fetch_field fields, str_printfa(str, "UID FETCH %u (", _mail->uid); if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0) str_append(str, "INTERNALDATE "); + if ((fields & MAIL_FETCH_SAVE_DATE) != 0) { + i_assert(HAS_ALL_BITS(mbox->capabilities, + IMAPC_CAPABILITY_SAVEDATE)); + str_append(str, "SAVEDATE "); + } if ((fields & (MAIL_FETCH_PHYSICAL_SIZE | MAIL_FETCH_VIRTUAL_SIZE)) != 0) str_append(str, "RFC822.SIZE "); if ((fields & MAIL_FETCH_GUID) != 0) { @@ -338,8 +343,12 @@ imapc_mail_get_wanted_fetch_fields(struct imapc_mail *mail) data->received_date == (time_t)-1) fields |= MAIL_FETCH_RECEIVED_DATE; if ((data->wanted_fields & MAIL_FETCH_SAVE_DATE) != 0 && - data->save_date == (time_t)-1 && data->received_date == (time_t)-1) - fields |= MAIL_FETCH_RECEIVED_DATE; + data->save_date == (time_t)-1) { + if (HAS_ALL_BITS(mbox->capabilities, IMAPC_CAPABILITY_SAVEDATE)) + fields |= MAIL_FETCH_SAVE_DATE; + else + fields |= MAIL_FETCH_RECEIVED_DATE; + } if ((data->wanted_fields & (MAIL_FETCH_PHYSICAL_SIZE | MAIL_FETCH_VIRTUAL_SIZE)) != 0 && data->physical_size == (uoff_t)-1 && @@ -410,11 +419,20 @@ bool imapc_mail_prefetch(struct mail *_mail) static bool imapc_mail_have_fields(struct imapc_mail *imail, enum mail_fetch_field fields) { + struct imapc_mailbox *mbox = IMAPC_MAILBOX(imail->imail.mail.mail.box); + if ((fields & MAIL_FETCH_RECEIVED_DATE) != 0) { if (imail->imail.data.received_date == (time_t)-1) return FALSE; fields &= ~MAIL_FETCH_RECEIVED_DATE; } + if ((fields & MAIL_FETCH_SAVE_DATE) != 0) { + i_assert(HAS_ALL_BITS(mbox->capabilities, + IMAPC_CAPABILITY_SAVEDATE)); + if (imail->imail.data.save_date == (time_t)-1) + return FALSE; + fields &= ~MAIL_FETCH_SAVE_DATE; + } if ((fields & (MAIL_FETCH_PHYSICAL_SIZE | MAIL_FETCH_VIRTUAL_SIZE)) != 0) { if (imail->imail.data.physical_size == (uoff_t)-1) return FALSE; @@ -826,8 +844,20 @@ void imapc_mail_fetch_update(struct imapc_mail *mail, match = TRUE; } else if (strcasecmp(key, "INTERNALDATE") == 0) { if (imap_arg_get_astring(&args[i+1], &value) && - imap_parse_datetime(value, &t, &tz)) + imap_parse_datetime(value, &t, &tz)) { mail->imail.data.received_date = t; + if (HAS_NO_BITS(mbox->capabilities, + IMAPC_CAPABILITY_SAVEDATE)) + mail->imail.data.save_date = t; + } + match = TRUE; + } else if (strcasecmp(key, "SAVEDATE") == 0) { + if (imap_arg_get_astring(&args[i+1], &value)) { + if (strcasecmp(value, "NIL") == 0) + mail->imail.data.save_date = 0; + else if (imap_parse_datetime(value, &t, &tz)) + mail->imail.data.save_date = t; + } match = TRUE; } else if (strcasecmp(key, "BODY") == 0) { if (IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_FETCH_BODYSTRUCTURE)) { diff --git a/src/lib-storage/index/imapc/imapc-mail.c b/src/lib-storage/index/imapc/imapc-mail.c index 414327f264..3ea21eb7b3 100644 --- a/src/lib-storage/index/imapc/imapc-mail.c +++ b/src/lib-storage/index/imapc/imapc-mail.c @@ -140,17 +140,29 @@ static int imapc_mail_get_received_date(struct mail *_mail, time_t *date_r) static int imapc_mail_get_save_date(struct mail *_mail, time_t *date_r) { + struct imapc_mailbox *mbox = IMAPC_MAILBOX(_mail->box); struct index_mail *mail = INDEX_MAIL(_mail); struct index_mail_data *data = &mail->data; - if (data->save_date == (time_t)-1) { - /* FIXME: we could use a value stored in cache */ + if (data->save_date != 0 && index_mail_get_save_date(_mail, date_r) > 0) + return 1; + + if (HAS_NO_BITS(mbox->capabilities, IMAPC_CAPABILITY_SAVEDATE)) { + data->save_date = 0; + } else if (data->save_date == (time_t)-1) { + if (imapc_mail_fetch(_mail, MAIL_FETCH_SAVE_DATE, NULL) < 0) + return -1; + if (data->save_date == (time_t)-1 && + imapc_mail_failed(_mail, "SAVEDATE") < 0) + return -1; + } + if (data->save_date == (time_t)-1 || data->save_date == 0) { if (imapc_mail_get_received_date(_mail, date_r) < 0) return -1; return 0; } *date_r = data->save_date; - return 0; + return 1; } static int imapc_mail_get_physical_size(struct mail *_mail, uoff_t *size_r) @@ -369,7 +381,9 @@ void imapc_mail_update_access_parts(struct index_mail *mail) if ((data->wanted_fields & MAIL_FETCH_RECEIVED_DATE) != 0) (void)index_mail_get_received_date(_mail, &date); if ((data->wanted_fields & MAIL_FETCH_SAVE_DATE) != 0) { - if (index_mail_get_save_date(_mail, &date) < 0) { + if (index_mail_get_save_date(_mail, &date) < 0 && + HAS_NO_BITS(mbox->capabilities, + IMAPC_CAPABILITY_SAVEDATE)) { (void)index_mail_get_received_date(_mail, &date); data->save_date = data->received_date; } diff --git a/src/lib-storage/index/imapc/imapc-search.c b/src/lib-storage/index/imapc/imapc-search.c index b776ae4212..e395919f34 100644 --- a/src/lib-storage/index/imapc/imapc-search.c +++ b/src/lib-storage/index/imapc/imapc-search.c @@ -96,7 +96,9 @@ imapc_build_search_query_arg(struct imapc_mailbox *mbox, return TRUE; case SEARCH_BEFORE: case SEARCH_SINCE: - if ((mbox->capabilities & IMAPC_CAPABILITY_WITHIN) == 0) { + case SEARCH_ON: + if (arg->type != SEARCH_ON && + (mbox->capabilities & IMAPC_CAPABILITY_WITHIN) == 0) { /* a bit kludgy way to check this.. */ size_t pos = str_len(str); if (!mail_search_arg_to_imap(str, arg, &error)) @@ -106,12 +108,17 @@ imapc_build_search_query_arg(struct imapc_mailbox *mbox, return FALSE; return TRUE; } + if (arg->value.date_type == MAIL_SEARCH_DATE_TYPE_SAVED && + (mbox->capabilities & IMAPC_CAPABILITY_SAVEDATE) == 0) { + /* Fall back to internal date if save date is not + supported. */ + arg2.value.date_type = MAIL_SEARCH_DATE_TYPE_RECEIVED; + } /* fall through */ case SEARCH_ALL: case SEARCH_UIDSET: case SEARCH_FLAGS: case SEARCH_KEYWORDS: - case SEARCH_ON: case SEARCH_SMALLER: case SEARCH_LARGER: case SEARCH_HEADER: @@ -126,6 +133,9 @@ imapc_build_search_query_arg(struct imapc_mailbox *mbox, return FALSE; return mail_search_arg_to_imap(str, arg, &error); case SEARCH_SAVEDATESUPPORTED: + if ((mbox->capabilities & IMAPC_CAPABILITY_SAVEDATE) == 0) + return FALSE; + return mail_search_arg_to_imap(str, arg, &error); case SEARCH_INTHREAD: case SEARCH_GUID: case SEARCH_MAILBOX: