static int index_mail_parse_bodystructure(struct index_mail *mail, enum index_cache_field field) { struct index_mail_data *data = &mail->data; string_t *str; if (data->parsed_bodystructure) { /* we have everything parsed already, but just not written to a string */ index_mail_body_parsed_cache_bodystructure(mail, field); } else { if (data->save_bodystructure_header || !data->save_bodystructure_body) { /* we haven't parsed the header yet */ data->save_bodystructure_header = TRUE; data->save_bodystructure_body = TRUE; (void)get_cached_parts(mail); if (index_mail_parse_headers(mail, NULL) < 0) return -1; } if (index_mail_parse_body(mail, field) < 0) return -1; } i_assert(data->parts != NULL); /* if we didn't want to have the body(structure) cached, it's still not written. */ switch (field) { case MAIL_CACHE_IMAP_BODY: if (data->body == NULL) { str = str_new(mail->data_pool, 128); imap_bodystructure_write(data->parts, str, FALSE); data->body = str_c(str); } break; case MAIL_CACHE_IMAP_BODYSTRUCTURE: if (data->bodystructure == NULL) { str = str_new(mail->data_pool, 128); imap_bodystructure_write(data->parts, str, TRUE); data->bodystructure = str_c(str); } break; default: i_unreached(); } return 0; }
static void test_imap_bodystructure_write(void) { struct message_part *parts; string_t *str = t_str_new(128); pool_t pool = pool_alloconly_create("imap bodystructure write", 1024); test_begin("imap bodystructure write"); parts = msg_parse(pool, TRUE); imap_bodystructure_write(parts, str, TRUE); test_assert(strcmp(str_c(str), testmsg_bodystructure) == 0); str_truncate(str, 0); imap_bodystructure_write(parts, str, FALSE); test_assert(strcmp(str_c(str), testmsg_body) == 0); pool_unref(&pool); test_end(); }
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); } }