Mercurial > dovecot > core-2.2
view src/lib-index/mbox/mbox-append.c @ 1745:7e3ce7515477 HEAD
mbox reading is kind of working again. Just don't try rewriting or expunging
:) Changing headers are also hidden from clients so mbox messages are finally
seen immutable as required by IMAP.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 03 Sep 2003 01:33:33 +0300 |
parents | 8920600a8cfc |
children | e42d97a85653 |
line wrap: on
line source
/* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" #include "ioloop.h" #include "istream.h" #include "hex-binary.h" #include "md5.h" #include "mbox-index.h" #include "mail-index-util.h" #include "mail-cache.h" static int mbox_index_append_next(struct mail_index *index, struct mail_cache_transaction_ctx *trans_ctx, struct istream *input) { struct mail_index_record *rec; struct mbox_header_context ctx; enum mail_index_record_flag index_flags; time_t received_date; uoff_t abs_start_offset, eoh_offset; const unsigned char *data; unsigned char md5_digest[16]; size_t size, pos; int dirty, save_md5 = FALSE; /* get the From-line */ pos = 0; while (i_stream_read_data(input, &data, &size, pos) > 0) { for (; pos < size; pos++) { if (data[pos] == '\n') break; } if (pos < size) break; } if (pos == size || size <= 5 || strncmp((const char *) data, "From ", 5) != 0) { /* a) no \n found, or line too long b) not a From-line */ index_set_error(index, "Error indexing mbox file %s: " "From-line not found where expected", index->mailbox_path); index->set_flags |= MAIL_INDEX_HDR_FLAG_FSCK; return -1; } /* parse the From-line */ received_date = mbox_from_parse_date(data + 5, size - 5); if (received_date == (time_t)-1) received_date = ioloop_time; i_stream_skip(input, pos+1); abs_start_offset = input->start_offset + input->v_offset; /* now, find the end of header. also stops at "\nFrom " if it's found (broken messages) */ mbox_skip_header(input); eoh_offset = input->v_offset; index_flags = 0; /* parse the header and cache wanted fields. get the message flags from Status and X-Status fields. temporarily limit the stream length so the message body is parsed properly. the stream length limit is raised again by mbox_header_cb after reading the headers. it uses Content-Length if available or finds the next From-line. */ mbox_header_init_context(&ctx, index, input); ctx.set_read_limit = TRUE; i_stream_seek(input, abs_start_offset - input->start_offset); i_stream_set_read_limit(input, eoh_offset); message_parse_header(NULL, input, NULL, mbox_header_cb, &ctx); i_stream_seek(input, input->v_limit); i_stream_set_read_limit(input, 0); dirty = ctx.content_length_broken; if (index->header->messages_count == 0 && ctx.uid_validity != index->header->uid_validity) { /* UID validity is different */ if (ctx.uid_validity != 0) { /* change it in index */ index->header->uid_validity = ctx.uid_validity; index->header->next_uid = 1; index->header->last_nonrecent_uid = 0; index->inconsistent = TRUE; } else if (!index->mailbox_readonly) { /* we have to write it to mbox */ if (index->mbox_lock_type != MAIL_LOCK_EXCLUSIVE) { /* try again */ return 0; } dirty = TRUE; } } if (ctx.uid >= index->header->next_uid) { /* X-UID header looks ok */ index->header->next_uid = ctx.uid; } else if (!index->mailbox_readonly) { /* Write X-UID for it */ dirty = TRUE; } else { /* save MD5 */ save_md5 = TRUE; } if (dirty && !index->mailbox_readonly) { if (index->mbox_lock_type != MAIL_LOCK_EXCLUSIVE) { /* try again */ return 0; } index->header->flags |= MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES; index_flags |= MAIL_INDEX_FLAG_DIRTY; } /* add message to index */ rec = index->append(index); if (rec == NULL) return -1; /* save message flags */ rec->msg_flags = ctx.flags; mail_index_mark_flag_changes(index, rec, 0, rec->msg_flags); if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_INDEX_FLAGS, &index_flags, sizeof(index_flags))) return -1; /* location offset = beginning of headers in message */ if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_LOCATION_OFFSET, &abs_start_offset, sizeof(abs_start_offset))) return -1; if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_RECEIVED_DATE, &received_date, sizeof(received_date))) return -1; if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_PHYSICAL_BODY_SIZE, &ctx.content_length, sizeof(ctx.content_length))) return -1; if (save_md5) { md5_final(&ctx.md5, md5_digest); if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_MD5, md5_digest, sizeof(md5_digest))) return -1; } return 1; } int mbox_index_append_stream(struct mail_index *index, struct istream *input) { struct mail_cache_transaction_ctx *trans_ctx; uoff_t offset; int ret; if (input->v_offset == input->v_size) { /* no new data */ return TRUE; } if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE)) return FALSE; if (mail_cache_transaction_begin(index->cache, TRUE, &trans_ctx) <= 0) return FALSE; do { offset = input->v_offset; if (input->start_offset + input->v_offset != 0) { /* we're at the [\r]\n before the From-line, skip it */ if (!mbox_skip_crlf(input)) { index_set_error(index, "Error indexing mbox file %s: " "LF not found where expected", index->mailbox_path); index->set_flags |= MAIL_INDEX_HDR_FLAG_FSCK; ret = -1; break; } } if (input->v_offset == input->v_size) { ret = 1; break; } t_push(); ret = mbox_index_append_next(index, trans_ctx, input); t_pop(); if (ret == 0) { /* we want to rescan this message with exclusive locking */ i_stream_seek(input, offset); } } while (ret > 0); if (ret >= 0 && index->mbox_lock_type == MAIL_LOCK_EXCLUSIVE) { /* Write missing X-IMAPbase and new/changed X-UID headers */ if (!mbox_index_rewrite(index)) ret = -1; } if (ret >= 0) { if (!mail_cache_transaction_commit(trans_ctx)) ret = -1; } if (!mail_cache_transaction_end(trans_ctx)) ret = -1; return ret >= 0; }