static void index_mail_body_parsed_cache_message_parts(struct index_mail *mail) { struct index_mail_data *data = &mail->data; unsigned int cache_field = mail->ibox->cache_fields[MAIL_CACHE_MESSAGE_PARTS].idx; enum mail_cache_decision_type decision; buffer_t *buffer; if (data->messageparts_saved_to_cache || mail_cache_field_exists(mail->trans->cache_view, mail->data.seq, cache_field) != 0) { /* already cached */ return; } decision = mail_cache_field_get_decision(mail->mail.mail.box->cache, cache_field); if (decision == (MAIL_CACHE_DECISION_NO | MAIL_CACHE_DECISION_FORCED)) { /* we never want it cached */ return; } if (decision == MAIL_CACHE_DECISION_NO && !data->save_message_parts && (mail->wanted_fields & MAIL_FETCH_MESSAGE_PARTS) == 0) { /* we didn't really care about the message parts themselves, just wanted to use something that depended on it */ return; } T_BEGIN { buffer = buffer_create_dynamic(pool_datastack_create(), 1024); message_part_serialize(mail->data.parts, buffer); index_mail_cache_add_idx(mail, cache_field, buffer->data, buffer->used); } T_END; data->messageparts_saved_to_cache = TRUE; }
static int maildir_get_pop3_state(struct index_mail *mail) { struct mailbox *box = mail->mail.mail.box; struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box); const struct mail_cache_field *fields; unsigned int i, count, psize_idx, vsize_idx; enum mail_cache_decision_type dec, vsize_dec; enum mail_fetch_field allowed_pop3_fields; bool not_pop3_only = FALSE; if (mail->pop3_state_set) return mail->pop3_state; /* if this mail itself has non-pop3 fields we know we're not pop3-only */ allowed_pop3_fields = MAIL_FETCH_FLAGS | MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY | MAIL_FETCH_STORAGE_ID | MAIL_FETCH_VIRTUAL_SIZE; if (mail->data.wanted_headers != NULL || (mail->data.wanted_fields & ~allowed_pop3_fields) != 0) not_pop3_only = TRUE; /* get vsize decisions */ psize_idx = ibox->cache_fields[MAIL_CACHE_PHYSICAL_FULL_SIZE].idx; vsize_idx = ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx; if (not_pop3_only) { vsize_dec = mail_cache_field_get_decision(box->cache, vsize_idx); vsize_dec &= ~MAIL_CACHE_DECISION_FORCED; } else { /* also check if there are any non-[pv]size cached fields */ vsize_dec = MAIL_CACHE_DECISION_NO; fields = mail_cache_register_get_list(box->cache, pool_datastack_create(), &count); for (i = 0; i < count; i++) { dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED; if (fields[i].idx == vsize_idx) vsize_dec = dec; else if (dec != MAIL_CACHE_DECISION_NO && fields[i].idx != psize_idx) not_pop3_only = TRUE; } } if (!not_pop3_only) { /* either nothing is cached, or only vsize is cached. */ mail->pop3_state = 1; } else if (vsize_dec != MAIL_CACHE_DECISION_YES && (box->flags & MAILBOX_FLAG_POP3_SESSION) == 0) { /* if virtual size isn't cached permanently, POP3 isn't being used */ mail->pop3_state = -1; } else { /* possibly a mixed pop3/imap */ mail->pop3_state = 0; } mail->pop3_state_set = TRUE; return mail->pop3_state; }
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); } }