mbox-sync-full.c revision 749c1abc1804e227afa6bae2d5ddf8bcc96e7cc4
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (C) 2002 Timo Sirainen */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const unsigned char *msg;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen while (i_stream_read_data(input, &msg, &size, 0) > 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (i = 0; i < size; i++) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic int verify_header_md5sum(struct mail_index *index,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen const unsigned char *old_digest;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* MD5 sums must match */
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen old_digest = index->lookup_field_raw(index, rec, DATA_FIELD_MD5, &size);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic int mail_update_header_size(struct mail_index *index,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* update FIELD_HDR_HEADER_SIZE */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen index->update_field_raw(update, DATA_HDR_HEADER_SIZE,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* reset FIELD_HDR_VIRTUAL_SIZE - we don't know it anymore */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen index->update_field_raw(update, DATA_HDR_VIRTUAL_SIZE,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* update DATA_FIELD_MESSAGEPART */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if ((rec->data_fields & DATA_FIELD_MESSAGEPART) == 0)
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen part_data = index->lookup_field_raw(index, rec, DATA_FIELD_MESSAGEPART,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* well, this wasn't expected but don't bother failing */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* copy & update the part data */
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen if (!message_part_serialize_update_header(part_data_copy, size,
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen "Corrupted cached message_part data (%s)",
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen index->update_field_raw(update, DATA_FIELD_MESSAGEPART,
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainenstatic int match_next_record(struct mail_index *index,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct mail_index_record **next_rec, int *dirty)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* skip the From-line */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen hdr_size = 0; body_offset = 0; hdr_size_fixed = FALSE;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (!mbox_mail_get_location(index, rec, NULL, NULL, &body_size))
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen /* possibly broken message, find the next From-line
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen and make sure header parser won't pass it. */
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen i_stream_set_read_limit(input, input->v_offset);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* get the MD5 sum of fixed headers and the current
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen message flags in Status and X-Status fields */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen message_parse_header(NULL, input, &hdr_parsed_size,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (verify_header_md5sum(index, rec, current_digest) &&
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen mbox_verify_end_of_body(input, body_offset + body_size)) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* valid message */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* update flags, unless we've changed them */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen if ((rec->index_flags & INDEX_MAIL_FLAG_DIRTY) == 0) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* update_flags() sets dirty flag, remove it */
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen /* update location */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (!mbox_mail_get_location(index, rec, &offset,
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen /* update size */
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen if (hdr_size != hdr_parsed_size.physical_size ) {
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen if (!mail_update_header_size(index, rec, update,
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen /* try next message */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic int mbox_sync_from_stream(struct mail_index *index,
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen const unsigned char *data;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen unsigned int seq;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* first make sure we start with a "From " line. If file is too
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen small, we'll just treat it as empty mbox file. */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (i_stream_read_data(input, &data, &size, 5) > 0 &&
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen strncmp((const char *) data, "From ", 5) != 0) {
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen index_set_error(index, "File isn't in mbox format: %s",
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* we'll go through the mailbox and index in order matching the
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen messages by their size and Message-ID. old mails aren't remembered,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen so we handle well only the cases when mail has been deleted. if
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen mails have been reordered (eg. sorted by someone) most of the mails
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen will show up as being new. if we really wanted to support that well,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen we could save the message-ids into hash but I don't know if it's
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen worth the trouble. */
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen /* we're at the [\r]\n before the From-line,
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen /* they just went and broke it, even while
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen we had it locked. */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen "Error syncing mbox file %s: "
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen "LF not found where expected",
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen if (!match_next_record(index, rec, seq, input, &rec, &dirty))
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen /* Get back to line before From */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* delete the rest of the records */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (!dirty && (index->header->flags & MAIL_INDEX_FLAG_DIRTY_MESSAGES)) {
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen /* no flags were dirty anymore, no need to rewrite */
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen index->header->flags &= ~MAIL_INDEX_FLAG_DIRTY_MESSAGES;
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen input = mbox_get_stream(index, 0, MAIL_LOCK_SHARED);