index-mail.c revision 7a54d58280aad8a64f266c61273ea1e8dff511a3
/* Copyright (C) 2002-2006 Timo Sirainen */
#include "lib.h"
#include "array.h"
#include "buffer.h"
#include "ioloop.h"
#include "istream.h"
#include "hex-binary.h"
#include "str.h"
#include "message-date.h"
#include "message-part-serialize.h"
#include "message-parser.h"
#include "imap-bodystructure.h"
#include "imap-envelope.h"
#include "mail-cache.h"
#include "index-storage.h"
#include "index-mail.h"
{ "date.sent", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
sizeof(struct mail_sent_date), 0 },
{ "date.received", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
sizeof(uint32_t), 0 },
{ "date.save", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
sizeof(uint32_t), 0 },
{ "size.virtual", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
sizeof(uoff_t), 0 },
{ "size.physical", 0, MAIL_CACHE_FIELD_FIXED_SIZE,
sizeof(uoff_t), 0 },
{ "imap.body", 0, MAIL_CACHE_FIELD_STRING, 0, 0 },
{ "imap.bodystructure", 0, MAIL_CACHE_FIELD_STRING, 0, 0 },
{ "imap.envelope", 0, MAIL_CACHE_FIELD_STRING, 0, 0 },
{ "mime.parts", 0, MAIL_CACHE_FIELD_VARIABLE_SIZE, 0, 0 }
};
enum index_cache_field field);
{
struct message_part *part;
const char *error;
t_push();
t_pop();
return FALSE;
}
t_pop();
"Corrupted cached message_part data (%s)", error);
return FALSE;
}
/* we know the NULs now, update them */
} else {
}
return TRUE;
}
enum index_cache_field field,
{
int ret;
t_push();
} else {
}
t_pop();
return ret;
}
enum index_cache_field field)
{
return uoff;
}
{
}
{
static const char *const no_keywords[] = { NULL };
const char *const *names;
const unsigned int *keyword_indexes;
unsigned int i, count, names_count;
t_push();
&keyword_indexes_arr) < 0) {
t_pop();
return NULL;
}
if (count == 0) {
t_pop();
return no_keywords;
}
for (i = 0; i < count; i++) {
const char *name;
}
/* end with NULL */
t_pop();
}
{
if (get_cached_parts(mail))
return NULL;
}
}
{
uint32_t t;
&t, sizeof(t)))
return (time_t)-1;
data->received_date = t;
}
return data->received_date;
}
{
uint32_t t;
&t, sizeof(t)))
return (time_t)-1;
}
}
{
const char *str;
time_t t;
int tz;
return;
/* 0 = not found / invalid */
t = 0;
tz = 0;
}
}
{
}
}
{
}
}
{
else
(void)get_cached_msgpart_sizes(mail);
}
{
return data->virtual_size;
return (uoff_t)-1;
return data->virtual_size;
}
{
return data->physical_size;
else
(void)get_cached_msgpart_sizes(mail);
return data->physical_size;
}
{
}
{
const struct mail_index_header *hdr;
/* First check if we've configured caching not to be used with
low enough message count. */
return;
}
}
struct message_header_line *hdr,
{
}
{
MAIL_FETCH_IMAP_BODYSTRUCTURE)) != 0)
return TRUE;
return TRUE;
return TRUE;
return FALSE;
}
{
unsigned int cache_flags_idx;
bool want_cached;
if (data->parsed_bodystructure &&
/* we need message_parts cached to be able to
actually use it in BODY/BODYSTRUCTURE reply */
want_cached = TRUE;
}
/* cache flags should never get unset as long as the message doesn't
change, but try to handle it anyway */
} else {
}
&cache_flags, sizeof(cache_flags));
}
}
{
unsigned int cache_field =
if (data->messageparts_saved_to_cache ||
cache_field) != 0) {
/* already cached */
return;
}
/* we never want it cached */
return;
}
if (decision == MAIL_CACHE_DECISION_NO &&
!data->save_message_parts &&
/* we didn't really care about the message parts themselves,
just wanted to use something that depended on it */
return;
}
t_push();
t_pop();
}
static void
enum index_cache_field field)
{
unsigned int cache_field_parts =
unsigned int cache_field_body =
unsigned int cache_field_bodystructure =
enum mail_cache_decision_type dec;
bool bodystructure_cached = FALSE;
bool plain_bodystructure = FALSE;
bool cache_bodystructure, cache_body;
if (data->messageparts_saved_to_cache ||
cache_field_parts) > 0) {
/* cached it as flag + message_parts */
}
}
/* 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)
else if (field == MAIL_CACHE_IMAP_BODYSTRUCTURE ||
} else {
}
if (cache_bodystructure) {
}
} else {
}
/* normally don't cache both BODY and BODYSTRUCTURE, but do it
if BODY is forced to be cached */
if (plain_bodystructure ||
cache_body = FALSE;
else if (field == MAIL_CACHE_IMAP_BODY) {
} else {
}
if (cache_body) {
}
}
}
{
static enum index_cache_field date_fields[] = {
};
unsigned int i, cache_field;
for (i = 0; i < N_ELEMENTS(date_fields); i++) {
}
}
}
enum index_cache_field field,
bool appended_mail)
{
if (appended_mail) {
MAIL_STORAGE_FLAG_SAVE_CRLF) != 0;
}
(void)get_cached_msgpart_sizes(mail);
}
enum index_cache_field field)
{
if (data->save_bodystructure_body) {
/* bodystructure header is parsed, we want the body's mime
headers too */
} else {
}
}
struct message_size *hdr_size,
struct message_size *body_size)
{
(void)get_cached_msgpart_sizes(mail);
if (!data->hdr_size_set) {
(void)get_cached_parts(mail);
return NULL;
} else {
}
}
}
if (!data->body_size_set) {
else {
}
}
}
}
}
enum index_cache_field field)
{
if (data->parsed_bodystructure) {
/* we have everything parsed already, but just not written to
a string */
return;
}
if (data->save_bodystructure_header ||
/* we haven't parsed the header yet */
(void)get_cached_parts(mail);
return;
}
}
static void
bool extended)
{
if (extended)
}
enum mail_fetch_field field)
{
const void *ext_data;
switch (field) {
case MAIL_FETCH_IMAP_BODY: {
unsigned int body_cache_field =
unsigned int bodystructure_cache_field =
/* 1) use plain-7bit-ascii flag if it exists
2) get BODY if it exists
3) get it using BODYSTRUCTURE if it exists
4) parse body structure, and save BODY/BODYSTRUCTURE
depending on what we want cached */
get_cached_parts(mail)) {
}
}
bodystructure_cache_field) > 0) {
str_truncate(str, 0);
}
/* broken, continue.. */
"Corrupted BODYSTRUCTURE for mail %u",
}
}
case MAIL_FETCH_IMAP_BODYSTRUCTURE: {
unsigned int bodystructure_cache_field =
return data->bodystructure;
get_cached_parts(mail)) {
}
bodystructure_cache_field) > 0) {
return data->bodystructure;
}
return data->bodystructure;
}
case MAIL_FETCH_IMAP_ENVELOPE:
case MAIL_FETCH_FROM_ENVELOPE:
return NULL;
case MAIL_FETCH_HEADER_MD5:
&ext_data) < 0) {
return NULL;
}
return NULL;
default:
i_unreached();
return NULL;
}
}
struct mail *
struct mailbox_header_lookup_ctx *_wanted_headers)
{
struct index_transaction_context *t =
(struct index_transaction_context *)_t;
struct index_header_lookup_ctx *wanted_headers =
(struct index_header_lookup_ctx *)_wanted_headers;
struct index_mail *mail;
const struct mail_index_header *hdr;
}
{
}
{
}
{
unsigned int cache_field_envelope =
unsigned int cache_field_hdr;
return;
}
/* if "imap.envelope" is cached, that's all we need */
cache_field_envelope) > 0)
return;
/* don't waste time doing full checks for all required
headers. assume that if we have "hdr.message-id" cached,
we don't need to parse the header. */
"hdr.message-id");
if (cache_field_hdr == (unsigned int)-1 ||
cache_field_hdr) <= 0)
}
{
const struct mail_index_record *rec;
return 0;
return -1;
}
MAIL_FETCH_IMAP_BODYSTRUCTURE)) != 0) {
&data->cache_flags,
sizeof(data->cache_flags));
}
/* set public fields */
unsigned int cache_field =
cache_field) <= 0) {
}
}
unsigned int cache_field =
}
/* we need either imap.body or imap.bodystructure */
unsigned int cache_field1 =
unsigned int cache_field2 =
seq, cache_field1) <= 0 &&
seq, cache_field2) <= 0) {
}
}
unsigned int cache_field =
cache_field) <= 0) {
}
}
unsigned int cache_field =
cache_field) <= 0) {
}
}
MAIL_FETCH_STREAM_BODY)) != 0) {
/* open stream immediately to set expunged flag if
it's already lost */
}
return 0;
}
{
return -1;
if (seq == 0) {
return 0;
}
return -1;
return 1;
}
{
}
{
struct message_block block;
int ret;
&block)) > 0) {
continue;
} else {
}
}
}
{
static enum index_cache_field date_fields[] = {
};
unsigned int i, cache_field;
uint32_t t;
for (i = 0; i < N_ELEMENTS(date_fields); i++) {
t = dates[i];
&t, sizeof(t));
}
}
}
{
/* this save_date may not be exactly the same as what we get
in future, but then again neither mbox nor maildir
guarantees it anyway. */
}
}
enum mail_flags flags)
{
return 0;
}
struct mail_keywords *keywords)
{
keywords);
return 0;
}
{
return 0;
}