static bool want_plain_bodystructure_cached(struct index_mail *mail) { if ((mail->wanted_fields & (MAIL_FETCH_IMAP_BODY | MAIL_FETCH_IMAP_BODYSTRUCTURE)) != 0) return TRUE; if (mail_cache_field_want_add(mail->trans->cache_trans, mail->data.seq, mail->ibox->cache_fields[MAIL_CACHE_IMAP_BODY].idx)) return TRUE; if (mail_cache_field_want_add(mail->trans->cache_trans, mail->data.seq, mail->ibox->cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx)) return TRUE; return FALSE; }
static void index_mail_body_parsed_cache_flags(struct index_mail *mail) { struct index_mail_data *data = &mail->data; unsigned int cache_flags_idx; uint32_t cache_flags = data->cache_flags; bool want_cached; cache_flags_idx = mail->ibox->cache_fields[MAIL_CACHE_FLAGS].idx; want_cached = mail_cache_field_want_add(mail->trans->cache_trans, data->seq, cache_flags_idx); if (data->parsed_bodystructure && imap_bodystructure_is_plain_7bit(data->parts) && (want_cached || want_plain_bodystructure_cached(mail))) { cache_flags |= MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII; /* we need message_parts cached to be able to actually use it in BODY/BODYSTRUCTURE reply */ want_cached = TRUE; data->save_message_parts = TRUE; } /* cache flags should never get unset as long as the message doesn't change, but try to handle it anyway */ cache_flags &= ~(MAIL_CACHE_FLAG_BINARY_HEADER | MAIL_CACHE_FLAG_BINARY_BODY | MAIL_CACHE_FLAG_HAS_NULS | MAIL_CACHE_FLAG_HAS_NO_NULS); if ((data->parts->flags & MESSAGE_PART_FLAG_HAS_NULS) != 0) { mail->mail.mail.has_nuls = TRUE; mail->mail.mail.has_no_nuls = FALSE; cache_flags |= MAIL_CACHE_FLAG_HAS_NULS; } else { mail->mail.mail.has_nuls = FALSE; mail->mail.mail.has_no_nuls = TRUE; cache_flags |= MAIL_CACHE_FLAG_HAS_NO_NULS; } if (data->hdr_size.virtual_size == data->hdr_size.physical_size) cache_flags |= MAIL_CACHE_FLAG_BINARY_HEADER; if (data->body_size.virtual_size == data->body_size.physical_size) cache_flags |= MAIL_CACHE_FLAG_BINARY_BODY; if (cache_flags != data->cache_flags && want_cached) { index_mail_cache_add_idx(mail, cache_flags_idx, &cache_flags, sizeof(cache_flags)); } data->cache_flags = cache_flags; }
static void index_mail_parse_header_register_all_wanted(struct index_mail *mail) { struct mail *_mail = &mail->mail.mail; const struct mail_cache_field *all_cache_fields; unsigned int i, count; all_cache_fields = mail_cache_register_get_list(_mail->box->cache, pool_datastack_create(), &count); for (i = 0; i < count; i++) { if (strncasecmp(all_cache_fields[i].name, "hdr.", 4) != 0) continue; if (!mail_cache_field_want_add(_mail->transaction->cache_trans, _mail->seq, i)) continue; array_idx_set(&mail->header_match, all_cache_fields[i].idx, &mail->header_match_value); } }
static bool index_mail_want_cache(struct index_mail *mail, enum index_cache_field field) { enum mail_fetch_field fetch_field; unsigned int cache_field; switch (field) { case MAIL_CACHE_SENT_DATE: fetch_field = MAIL_FETCH_DATE; break; case MAIL_CACHE_RECEIVED_DATE: fetch_field = MAIL_FETCH_RECEIVED_DATE; break; case MAIL_CACHE_SAVE_DATE: fetch_field = MAIL_FETCH_SAVE_DATE; break; case MAIL_CACHE_VIRTUAL_FULL_SIZE: fetch_field = MAIL_FETCH_VIRTUAL_SIZE; break; case MAIL_CACHE_PHYSICAL_FULL_SIZE: fetch_field = MAIL_FETCH_PHYSICAL_SIZE; break; default: i_unreached(); } if ((mail->data.dont_cache_fetch_fields & fetch_field) != 0) return FALSE; cache_field = mail->ibox->cache_fields[field].idx; if ((mail->data.cache_fetch_fields & fetch_field) != 0) { return mail_cache_field_can_add(mail->trans->cache_trans, mail->data.seq, cache_field); } else { return mail_cache_field_want_add(mail->trans->cache_trans, mail->data.seq, cache_field); } }
static void index_mail_body_parsed_cache_bodystructure(struct index_mail *mail, enum index_cache_field field) { struct index_mail_data *data = &mail->data; unsigned int cache_field_parts = mail->ibox->cache_fields[MAIL_CACHE_MESSAGE_PARTS].idx; unsigned int cache_field_body = mail->ibox->cache_fields[MAIL_CACHE_IMAP_BODY].idx; unsigned int cache_field_bodystructure = mail->ibox->cache_fields[MAIL_CACHE_IMAP_BODYSTRUCTURE].idx; enum mail_cache_decision_type dec; string_t *str; bool bodystructure_cached = FALSE; bool plain_bodystructure = FALSE; bool cache_bodystructure, cache_body; if ((data->cache_flags & MAIL_CACHE_FLAG_TEXT_PLAIN_7BIT_ASCII) != 0) { if (data->messageparts_saved_to_cache || mail_cache_field_exists(mail->trans->cache_view, data->seq, cache_field_parts) > 0) { /* cached it as flag + message_parts */ plain_bodystructure = TRUE; } } if (!data->parsed_bodystructure) return; /* If BODY is fetched first but BODYSTRUCTURE is also wanted, we don't normally want to first cache BODY and then BODYSTRUCTURE. So check the wanted_fields also in here. */ if (plain_bodystructure) cache_bodystructure = FALSE; else if (field == MAIL_CACHE_IMAP_BODYSTRUCTURE || (mail->wanted_fields & MAIL_FETCH_IMAP_BODYSTRUCTURE) != 0) { cache_bodystructure = mail_cache_field_can_add(mail->trans->cache_trans, data->seq, cache_field_bodystructure); } else { cache_bodystructure = mail_cache_field_want_add(mail->trans->cache_trans, data->seq, cache_field_bodystructure); } if (cache_bodystructure) { str = str_new(mail->data_pool, 128); imap_bodystructure_write(data->parts, str, TRUE); data->bodystructure = str_c(str); index_mail_cache_add(mail, MAIL_CACHE_IMAP_BODYSTRUCTURE, str_c(str), str_len(str)+1); bodystructure_cached = TRUE; } else { bodystructure_cached = mail_cache_field_exists(mail->trans->cache_view, data->seq, cache_field_bodystructure) > 0; } /* normally don't cache both BODY and BODYSTRUCTURE, but do it if BODY is forced to be cached */ dec = mail_cache_field_get_decision(mail->mail.mail.box->cache, cache_field_body); if (plain_bodystructure || (bodystructure_cached && (dec != (MAIL_CACHE_DECISION_FORCED | MAIL_CACHE_DECISION_YES)))) cache_body = FALSE; else if (field == MAIL_CACHE_IMAP_BODY) { cache_body = mail_cache_field_can_add(mail->trans->cache_trans, data->seq, cache_field_body); } else { cache_body = mail_cache_field_want_add(mail->trans->cache_trans, data->seq, cache_field_body); } if (cache_body) { str = str_new(mail->data_pool, 128); imap_bodystructure_write(data->parts, str, FALSE); data->body = str_c(str); index_mail_cache_add(mail, MAIL_CACHE_IMAP_BODY, str_c(str), str_len(str)+1); } }