bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2018 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"
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen#include "index-pop3-uidl.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
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{
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_mail *mail = 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 =
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek 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{
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_mail *mail = 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{
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_mail *mail = DBOX_MAIL(_mail);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct index_mail_data *data = &mail->imail.data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *value;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch uintmax_t size;
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
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (str_to_uintmax_hex(value, &size) < 0 || size > (uoff_t)-1)
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch return -1;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch data->virtual_size = (uoff_t)size;
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{
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_mail *mail = DBOX_MAIL(_mail);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct index_mail_data *data = &mail->imail.data;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *value;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch uintmax_t time;
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
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch time = 0;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (value != NULL && str_to_uintmax_hex(value, &time) < 0)
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch return -1;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch data->received_date = (time_t)time;
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{
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_storage *storage = DBOX_STORAGE(_mail->box->storage);
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_mail *mail = 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;
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen uint32_t order;
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) {
bcc25e5a1f75ab94b53a2b32c4b382aece86289cTimo Sirainen if (cache_field == MAIL_CACHE_POP3_ORDER) {
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen i_assert(str_len(str) == sizeof(order));
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen memcpy(&order, str_data(str), sizeof(order));
bcc25e5a1f75ab94b53a2b32c4b382aece86289cTimo Sirainen str_truncate(str, 0);
baa93d5ed7c015309dc51aa238f8d0c79561121fTimo Sirainen if (order != 0)
baa93d5ed7c015309dc51aa238f8d0c79561121fTimo Sirainen str_printfa(str, "%u", order);
baa93d5ed7c015309dc51aa238f8d0c79561121fTimo Sirainen else {
baa93d5ed7c015309dc51aa238f8d0c79561121fTimo Sirainen /* order=0 means it doesn't exist. we don't
baa93d5ed7c015309dc51aa238f8d0c79561121fTimo Sirainen want to return "0" though, because then the
baa93d5ed7c015309dc51aa238f8d0c79561121fTimo Sirainen mails get ordered to beginning, while
baa93d5ed7c015309dc51aa238f8d0c79561121fTimo Sirainen nonexistent are supposed to be ordered at
baa93d5ed7c015309dc51aa238f8d0c79561121fTimo Sirainen the end. */
baa93d5ed7c015309dc51aa238f8d0c79561121fTimo Sirainen }
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen }
bcc25e5a1f75ab94b53a2b32c4b382aece86289cTimo 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 = "";
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen if (cache_field != MAIL_CACHE_POP3_ORDER) {
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen index_mail_cache_add_idx(imail, ibox->cache_fields[cache_field].idx,
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen value, strlen(value)+1);
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen } else {
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen if (str_to_uint(value, &order) < 0)
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen order = 0;
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen index_mail_cache_add_idx(imail, ibox->cache_fields[cache_field].idx,
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen &order, sizeof(order));
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen }
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{
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_mail *mail = DBOX_MAIL(_mail);
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen int ret;
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:
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen if (!index_pop3_uidl_can_exist(_mail)) {
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen *value_r = "";
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen return 0;
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen }
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen ret = dbox_get_cached_metadata(mail, DBOX_METADATA_POP3_UIDL,
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen MAIL_CACHE_POP3_UIDL, value_r);
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen if (ret == 0) {
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen index_pop3_uidl_update_exists(&mail->imail.mail.mail,
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen (*value_r)[0] != '\0');
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen }
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen return ret;
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen case MAIL_FETCH_POP3_ORDER:
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen if (!index_pop3_uidl_can_exist(_mail)) {
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen /* we're assuming that if there's a POP3 order, there's
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen also a UIDL */
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen *value_r = "";
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen return 0;
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen }
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen return dbox_get_cached_metadata(mail, DBOX_METADATA_POP3_ORDER,
147a788fea2a88f7125b27226451271d55cf5b01Timo Sirainen MAIL_CACHE_POP3_ORDER, 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{
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_storage *storage = DBOX_STORAGE(_mail->box->storage);
804fa3f03bd9170272168a5ad214053bbe3160c7Josef 'Jeff' Sipek struct dbox_mail *mail = 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);
204ee6ed414f5e4eeb6f6c10763b55daf56f11acJosef 'Jeff' Sipek 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}