dbox-mail.c revision a4d796994ba01c207f1d3e373f58f06c6779af53
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2007-2013 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "lib.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "istream.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "str.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "index-storage.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "index-mail.h"
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen#include "dbox-attachment.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "dbox-storage.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "dbox-file.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "dbox-mail.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include <stdlib.h>
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct mail *
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainendbox_mail_alloc(struct mailbox_transaction_context *t,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen enum mail_fetch_field wanted_fields,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mailbox_header_lookup_ctx *wanted_headers)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct dbox_mail *mail;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen pool_t pool;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
4c1deab456fe8877bf025d11843167ac1f36327aTimo Sirainen pool = pool_alloconly_create("mail", 2048);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail = p_new(pool, struct dbox_mail, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail->imail.mail.pool = pool;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen index_mail_init(&mail->imail, t, wanted_fields, wanted_headers);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return &mail->imail.mail.mail;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid dbox_mail_close(struct mail *_mail)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct dbox_mail *mail = (struct dbox_mail *)_mail;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
010affb9f4b9cca9b94e1d8d570cf179daff08d7Timo Sirainen index_mail_close(_mail);
010affb9f4b9cca9b94e1d8d570cf179daff08d7Timo Sirainen /* close the dbox file only after index is closed, since it may still
010affb9f4b9cca9b94e1d8d570cf179daff08d7Timo Sirainen try to read from it. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mail->open_file != NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_file_unref(&mail->open_file);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_mail_metadata_read(struct dbox_mail *mail, struct dbox_file **file_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct dbox_storage *storage =
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (struct dbox_storage *)mail->imail.mail.mail.box->storage;
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen uoff_t offset;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (storage->v.mail_open(mail, &offset, file_r) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
a81b240cfe84231eac64084efd5b0e1e91a9e817Timo Sirainen if (dbox_file_seek(*file_r, offset) <= 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (dbox_file_metadata_read(*file_r) <= 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen if (mail->imail.data.stream != NULL) {
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen /* we just messed up mail's input stream by reading metadata */
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen i_stream_seek((*file_r)->input, offset);
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen i_stream_sync(mail->imail.data.stream);
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen }
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen return 0;
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen}
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainenstatic int
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainendbox_mail_metadata_get(struct dbox_mail *mail, enum dbox_metadata_key key,
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen const char **value_r)
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen{
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen struct dbox_file *file;
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen if (dbox_mail_metadata_read(mail, &file) < 0)
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen return -1;
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen *value_r = dbox_file_metadata_get(file, key);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen struct dbox_mail *mail = (struct dbox_mail *)_mail;
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen struct index_mail_data *data = &mail->imail.data;
d7b205394bd07152718152976dfa089e13253d7eTimo Sirainen struct dbox_file *file;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (index_mail_get_physical_size(_mail, size_r) == 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
d7b205394bd07152718152976dfa089e13253d7eTimo Sirainen if (dbox_mail_metadata_read(mail, &file) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
427ad9fea54628d52f04c8a76269749a8e6fae7aTimo Sirainen data->physical_size = dbox_file_get_plaintext_size(file);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *size_r = data->physical_size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct dbox_mail *mail = (struct dbox_mail *)_mail;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct index_mail_data *data = &mail->imail.data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *value;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (index_mail_get_cached_virtual_size(&mail->imail, size_r))
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen if (dbox_mail_metadata_get(mail, DBOX_METADATA_VIRTUAL_SIZE,
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen &value) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (value == NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return index_mail_get_virtual_size(_mail, size_r);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen data->virtual_size = strtoul(value, NULL, 16);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *size_r = data->virtual_size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_mail_get_received_date(struct mail *_mail, time_t *date_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct dbox_mail *mail = (struct dbox_mail *)_mail;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct index_mail_data *data = &mail->imail.data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *value;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (index_mail_get_received_date(_mail, date_r) == 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen if (dbox_mail_metadata_get(mail, DBOX_METADATA_RECEIVED_TIME,
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen &value) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen data->received_date = value == NULL ? 0 : strtoul(value, NULL, 16);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *date_r = data->received_date;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_mail_get_save_date(struct mail *_mail, time_t *date_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
ea1f67e14d727496179ee4ff391f592bce8f4f2dTimo Sirainen struct dbox_storage *storage =
ea1f67e14d727496179ee4ff391f592bce8f4f2dTimo Sirainen (struct dbox_storage *)_mail->box->storage;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct dbox_mail *mail = (struct dbox_mail *)_mail;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct index_mail_data *data = &mail->imail.data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct dbox_file *file;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct stat st;
ea1f67e14d727496179ee4ff391f592bce8f4f2dTimo Sirainen uoff_t offset;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (index_mail_get_save_date(_mail, date_r) == 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
ea1f67e14d727496179ee4ff391f592bce8f4f2dTimo Sirainen if (storage->v.mail_open(mail, &offset, &file) < 0)
ea1f67e14d727496179ee4ff391f592bce8f4f2dTimo Sirainen return -1;
ea1f67e14d727496179ee4ff391f592bce8f4f2dTimo Sirainen
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen _mail->transaction->stats.fstat_lookup_count++;
b8d314c6355009ad0b9e332b6acecdfac5cc8891Timo Sirainen if (dbox_file_stat(file, &st) < 0) {
b8d314c6355009ad0b9e332b6acecdfac5cc8891Timo Sirainen if (errno == ENOENT)
b8d314c6355009ad0b9e332b6acecdfac5cc8891Timo Sirainen mail_set_expunged(_mail);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
b8d314c6355009ad0b9e332b6acecdfac5cc8891Timo Sirainen *date_r = data->save_date = st.st_ctime;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic int
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainendbox_get_cached_metadata(struct dbox_mail *mail, enum dbox_metadata_key key,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen enum index_cache_field cache_field,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char **value_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct index_mail *imail = &mail->imail;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct index_mailbox_context *ibox =
d22301419109ed4a38351715e6760011421dadecTimo Sirainen INDEX_STORAGE_CONTEXT(imail->mail.mail.box);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *value;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen string_t *str;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
5f44975ec6c5755dd74bcd4c47a123a7242ecab3Timo Sirainen str = str_new(imail->mail.data_pool, 64);
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen if (mail_cache_lookup_field(imail->mail.mail.transaction->cache_view,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen str, imail->mail.mail.seq,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ibox->cache_fields[cache_field].idx) > 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *value_r = str_c(str);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen if (dbox_mail_metadata_get(mail, key, &value) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (value == NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen value = "";
d22301419109ed4a38351715e6760011421dadecTimo Sirainen index_mail_cache_add_idx(imail, ibox->cache_fields[cache_field].idx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen value, strlen(value)+1);
0dc7a67fb62b2aac82ff1c03319bd4976c56dbc1Timo Sirainen
0dc7a67fb62b2aac82ff1c03319bd4976c56dbc1Timo Sirainen /* don't return pointer to dbox metadata directly, since it may
0dc7a67fb62b2aac82ff1c03319bd4976c56dbc1Timo Sirainen change unexpectedly */
0dc7a67fb62b2aac82ff1c03319bd4976c56dbc1Timo Sirainen str_truncate(str, 0);
0dc7a67fb62b2aac82ff1c03319bd4976c56dbc1Timo Sirainen str_append(str, value);
0dc7a67fb62b2aac82ff1c03319bd4976c56dbc1Timo Sirainen *value_r = str_c(str);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint dbox_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char **value_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct dbox_mail *mail = (struct dbox_mail *)_mail;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* keep the UIDL in cache file, otherwise POP3 would open all
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail files and read the metadata. same for GUIDs if they're
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen used. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen switch (field) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen case MAIL_FETCH_UIDL_BACKEND:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return dbox_get_cached_metadata(mail, DBOX_METADATA_POP3_UIDL,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen MAIL_CACHE_POP3_UIDL, value_r);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen case MAIL_FETCH_GUID:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return dbox_get_cached_metadata(mail, DBOX_METADATA_GUID,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen MAIL_CACHE_GUID, value_r);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen default:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen break;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return index_mail_get_special(_mail, field, value_r);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainenstatic int
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainenget_mail_stream(struct dbox_mail *mail, uoff_t offset,
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen struct istream **stream_r)
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen{
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen struct mail_private *pmail = &mail->imail.mail;
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen struct dbox_file *file = mail->open_file;
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen int ret;
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen
a4d796994ba01c207f1d3e373f58f06c6779af53Timo Sirainen if ((ret = dbox_file_seek(file, offset)) <= 0) {
a4d796994ba01c207f1d3e373f58f06c6779af53Timo Sirainen *stream_r = NULL;
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen return ret;
a4d796994ba01c207f1d3e373f58f06c6779af53Timo Sirainen }
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen *stream_r = i_stream_create_limit(file->input, file->cur_physical_size);
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen if (pmail->v.istream_opened != NULL) {
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen if (pmail->v.istream_opened(&pmail->mail, stream_r) < 0)
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen return -1;
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen }
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen if (file->storage->attachment_dir == NULL)
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen return 1;
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen else
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen return dbox_attachment_file_get_stream(file, stream_r);
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen}
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen
6df0ab0c1ab91f06b6418cb30eff44405a1b8f02Timo Sirainenint dbox_mail_get_stream(struct mail *_mail, bool get_body ATTR_UNUSED,
6df0ab0c1ab91f06b6418cb30eff44405a1b8f02Timo Sirainen struct message_size *hdr_size,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct message_size *body_size,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct istream **stream_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct dbox_storage *storage =
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (struct dbox_storage *)_mail->box->storage;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct dbox_mail *mail = (struct dbox_mail *)_mail;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct index_mail_data *data = &mail->imail.data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct istream *input;
b58aafbd21b365117538f73f306d22f75acd91f1Timo Sirainen uoff_t offset;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen int ret;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (data->stream == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (storage->v.mail_open(mail, &offset, &mail->open_file) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen ret = get_mail_stream(mail, offset, &input);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ret <= 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ret < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dbox_file_set_corrupted(mail->open_file,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "uid=%u points to broken data at offset="
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen "%"PRIuUOFF_T, _mail->uid, offset);
a4d796994ba01c207f1d3e373f58f06c6779af53Timo Sirainen if (input != NULL)
a4d796994ba01c207f1d3e373f58f06c6779af53Timo Sirainen i_stream_unref(&input);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen data->stream = input;
c853a862402035236200982bab5d6d25fce5162fTimo Sirainen index_mail_set_read_buffer_size(_mail, input);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return index_mail_init_stream(&mail->imail, hdr_size, body_size,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen stream_r);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}