index-fetch.c revision 02b32cf39a098edf60981fc228e4b034f11f3b90
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (C) 2002 Timo Sirainen */
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "lib.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "iobuffer.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "temp-string.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "mail-custom-flags.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "index-storage.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "index-fetch.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "index-messageset.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "message-send.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "imap-date.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "imap-util.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include "imap-message-cache.h"
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi#include <unistd.h>
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic int index_fetch_body(MailIndexRecord *rec, FetchContext *ctx)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi const char *body;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi body = imap_msgcache_get(ctx->cache, IMAP_CACHE_BODY);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (body != NULL) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi t_string_printfa(ctx->str, "BODY %s ", body);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return TRUE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi } else {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi i_error("Couldn't generate BODY for UID %u (index %s)",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi rec->uid, ctx->index->filepath);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic int index_fetch_bodystructure(MailIndexRecord *rec, FetchContext *ctx)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi const char *bodystructure;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi bodystructure = imap_msgcache_get(ctx->cache, IMAP_CACHE_BODYSTRUCTURE);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (bodystructure != NULL) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi t_string_printfa(ctx->str, "BODYSTRUCTURE %s ",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi bodystructure);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return TRUE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi } else {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi i_error("Couldn't generate BODYSTRUCTURE for UID %u (index %s)",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi rec->uid, ctx->index->filepath);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic int index_fetch_envelope(MailIndexRecord *rec, FetchContext *ctx)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi const char *envelope;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi envelope = imap_msgcache_get(ctx->cache, IMAP_CACHE_ENVELOPE);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (envelope != NULL) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi t_string_printfa(ctx->str, "ENVELOPE (%s) ", envelope);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return TRUE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi } else {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi i_error("Couldn't generate ENVELOPE for UID %u (index %s)",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi rec->uid, ctx->index->filepath);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic int index_fetch_rfc822_size(MailIndexRecord *rec, FetchContext *ctx)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi MessageSize hdr_size, body_size;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (!imap_msgcache_get_rfc822(ctx->cache, NULL,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi &hdr_size, &body_size)) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi i_error("Couldn't get RFC822.SIZE for UID %u (index %s)",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi rec->uid, ctx->index->filepath);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi t_string_printfa(ctx->str, "RFC822.SIZE %"PRIuUOFF_T" ",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi hdr_size.virtual_size + body_size.virtual_size);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return TRUE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic void index_fetch_flags(MailIndexRecord *rec, FetchContext *ctx)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi MailFlags flags;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi flags = rec->msg_flags;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (rec->uid >= ctx->index->first_recent_uid)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi flags |= MAIL_RECENT;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ctx->update_seen)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi flags |= MAIL_SEEN;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi t_string_printfa(ctx->str, "FLAGS (%s) ",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi imap_write_flags(flags, ctx->custom_flags));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic void index_fetch_internaldate(MailIndexRecord *rec, FetchContext *ctx)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi t_string_printfa(ctx->str, "INTERNALDATE \"%s\" ",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi imap_to_datetime(rec->internal_date));
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic void index_fetch_uid(MailIndexRecord *rec, FetchContext *ctx)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi t_string_printfa(ctx->str, "UID %u ", rec->uid);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic int index_fetch_send_rfc822(MailIndexRecord *rec, FetchContext *ctx)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi MessageSize hdr_size, body_size;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi IOBuffer *inbuf;
84b746f56209d4a85af73cd26850e75f519ae0b0Timo Sirainen const char *str;
84b746f56209d4a85af73cd26850e75f519ae0b0Timo Sirainen
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi &hdr_size, &body_size)) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi i_error("Couldn't get RFC822 for UID %u (index %s)",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi rec->uid, ctx->index->filepath);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi str = t_strdup_printf(" RFC822 {%"PRIuUOFF_T"}\r\n",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi hdr_size.virtual_size + body_size.virtual_size);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ctx->first) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi str++; ctx->first = FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi body_size.physical_size += hdr_size.physical_size;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi body_size.virtual_size += hdr_size.virtual_size;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return message_send(ctx->outbuf, inbuf, &body_size, 0, (uoff_t)-1);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic int index_fetch_send_rfc822_header(MailIndexRecord *rec,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi FetchContext *ctx)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi MessageSize hdr_size;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi IOBuffer *inbuf;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi const char *str;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf, &hdr_size, NULL)) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi i_error("Couldn't get RFC822.HEADER for UID %u (index %s)",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi rec->uid, ctx->index->filepath);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi str = t_strdup_printf(" RFC822.HEADER {%"PRIuUOFF_T"}\r\n",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi hdr_size.virtual_size);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ctx->first) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi str++; ctx->first = FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return message_send(ctx->outbuf, inbuf, &hdr_size, 0, (uoff_t)-1);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic int index_fetch_send_rfc822_text(MailIndexRecord *rec, FetchContext *ctx)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi MessageSize body_size;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi IOBuffer *inbuf;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi const char *str;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (!imap_msgcache_get_rfc822(ctx->cache, &inbuf, NULL, &body_size)) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi i_error("Couldn't get RFC822.TEXT for UID %u (index %s)",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi rec->uid, ctx->index->filepath);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi str = t_strdup_printf(" RFC822.TEXT {%"PRIuUOFF_T"}\r\n",
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi body_size.virtual_size);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ctx->first) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi str++; ctx->first = FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (io_buffer_send(ctx->outbuf, str, strlen(str)) < 0)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return message_send(ctx->outbuf, inbuf, &body_size, 0, (uoff_t)-1);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic ImapCacheField index_get_cache(MailFetchData *fetch_data)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi MailFetchBodyData *sect;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ImapCacheField field;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi field = 0;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (fetch_data->body)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi field |= IMAP_CACHE_BODY;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (fetch_data->bodystructure)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi field |= IMAP_CACHE_BODYSTRUCTURE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (fetch_data->envelope)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi field |= IMAP_CACHE_ENVELOPE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (fetch_data->rfc822_size) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi field |= IMAP_CACHE_MESSAGE_HDR_SIZE |
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi IMAP_CACHE_MESSAGE_BODY_SIZE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (fetch_data->rfc822) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi field |= IMAP_CACHE_MESSAGE_OPEN | IMAP_CACHE_MESSAGE_HDR_SIZE |
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi IMAP_CACHE_MESSAGE_BODY_SIZE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi }
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (fetch_data->rfc822_header)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi field |= IMAP_CACHE_MESSAGE_OPEN | IMAP_CACHE_MESSAGE_HDR_SIZE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (fetch_data->rfc822_text)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi field |= IMAP_CACHE_MESSAGE_OPEN | IMAP_CACHE_MESSAGE_BODY_SIZE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi /* check what body[] sections want */
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi sect = fetch_data->body_sections;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi for (; sect != NULL; sect = sect->next)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi field |= index_fetch_body_get_cache(sect->section);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return field;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic void index_msgcache_open(FetchContext *ctx, MailIndexRecord *rec)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ImapCacheField fields;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi uoff_t virtual_header_size, virtual_body_size;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi void *mail_cache_context;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi fields = index_get_cache(ctx->fetch_data);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (fields == 0)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi return;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi mail_cache_context = index_msgcache_get_context(ctx->index, rec);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi virtual_header_size =
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi (rec->index_flags & INDEX_MAIL_FLAG_BINARY_HEADER) ?
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi rec->header_size : 0;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi virtual_body_size =
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi (rec->index_flags & INDEX_MAIL_FLAG_BINARY_BODY) ?
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi rec->body_size : 0;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi imap_msgcache_open(ctx->cache, rec->uid, fields,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi virtual_header_size, virtual_body_size,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi mail_cache_context);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi}
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomistatic int index_fetch_mail(MailIndex *index __attr_unused__,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi MailIndexRecord *rec, unsigned int seq,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi void *context)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi{
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi FetchContext *ctx = context;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi MailFetchBodyData *sect;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi unsigned int orig_len;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi int failed, data_written;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ctx->str = t_string_new(2048);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi t_string_printfa(ctx->str, "* %u FETCH (", seq);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi orig_len = ctx->str->len;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi /* first see what we need to do. this way we don't first do some
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi light parsing and later notice that we need to do heavier parsing
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi anyway */
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi index_msgcache_open(ctx, rec);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi failed = TRUE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi data_written = FALSE;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi do {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi /* these can't fail */
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ctx->fetch_data->uid)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi index_fetch_uid(rec, ctx);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ctx->fetch_data->flags)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi index_fetch_flags(rec, ctx);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ctx->fetch_data->internaldate)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi index_fetch_internaldate(rec, ctx);
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi /* rest can */
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ctx->fetch_data->body)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (!index_fetch_body(rec, ctx))
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi break;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ctx->fetch_data->bodystructure)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (!index_fetch_bodystructure(rec, ctx))
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi break;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ctx->fetch_data->envelope)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (!index_fetch_envelope(rec, ctx))
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi break;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ctx->fetch_data->rfc822_size)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (!index_fetch_rfc822_size(rec, ctx))
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi break;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi /* send the data written into temp string,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi not including the trailing zero */
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ctx->first = ctx->str->len == orig_len;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (ctx->str->len > 0) {
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (!ctx->first)
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ctx->str->len--;
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi if (io_buffer_send(ctx->outbuf, ctx->str->str,
4d9181518769b1f78d8078f7fae899fd0b95907fAki Tuomi ctx->str->len) < 0)
break;
}
data_written = TRUE;
/* large data */
if (ctx->fetch_data->rfc822)
if (!index_fetch_send_rfc822(rec, ctx))
break;
if (ctx->fetch_data->rfc822_text)
if (!index_fetch_send_rfc822_text(rec, ctx))
break;
if (ctx->fetch_data->rfc822_header)
if (!index_fetch_send_rfc822_header(rec, ctx))
break;
sect = ctx->fetch_data->body_sections;
for (; sect != NULL; sect = sect->next) {
if (!index_fetch_body_section(rec, seq, sect, ctx))
break;
}
failed = FALSE;
} while (0);
if (data_written) {
if (io_buffer_send(ctx->outbuf, ")\r\n", 3) < 0)
failed = TRUE;
}
imap_msgcache_close(ctx->cache);
return !failed;
}
int index_storage_fetch(Mailbox *box, MailFetchData *fetch_data,
IOBuffer *outbuf, int *all_found)
{
IndexMailbox *ibox = (IndexMailbox *) box;
FetchContext ctx;
MailFetchBodyData *sect;
int ret;
if (!ibox->index->sync(ibox->index))
return mail_storage_set_index_error(ibox);
if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_SHARED))
return mail_storage_set_index_error(ibox);
memset(&ctx, 0, sizeof(ctx));
ctx.box = box;
ctx.cache = ibox->cache;
ctx.index = ibox->index;
ctx.custom_flags =
mail_custom_flags_list_get(ibox->index->custom_flags);
ctx.fetch_data = fetch_data;
ctx.outbuf = outbuf;
/* If we have any BODY[..] sections, \Seen flag is added for
all messages */
sect = ctx.fetch_data->body_sections;
for (; sect != NULL; sect = sect->next) {
if (!sect->peek) {
ctx.update_seen = TRUE;
break;
}
}
ret = index_messageset_foreach(ibox, fetch_data->messageset,
fetch_data->uidset,
index_fetch_mail, &ctx);
mail_custom_flags_list_unref(ibox->index->custom_flags);
if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK))
return mail_storage_set_index_error(ibox);
if (all_found != NULL)
*all_found = ret == 1;
if (ret >= 1 && ctx.update_seen && !box->readonly) {
/* BODY[..] was fetched, set \Seen flag for all messages.
This needs to be done separately because we need exclusive
lock for it */
if (!index_storage_update_flags(box, fetch_data->messageset,
fetch_data->uidset,
MAIL_SEEN, NULL, MODIFY_ADD,
NULL, NULL, NULL))
return FALSE;
}
return ret >= 0;
}