From: Timo Sirainen Date: Sun, 20 Jun 2004 13:03:02 +0000 (+0300) Subject: Don't die horribly when message with previously expunged UID is inserted X-Git-Tag: 1.1.alpha1~3895 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6843896c40bee4f9b6680ca7ced598c446e9f999;p=thirdparty%2Fdovecot%2Fcore.git Don't die horribly when message with previously expunged UID is inserted into mbox. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/mbox/mbox-sync-parse.c b/src/lib-storage/index/mbox/mbox-sync-parse.c index 779ec2b17d..396e5c41e0 100644 --- a/src/lib-storage/index/mbox/mbox-sync-parse.c +++ b/src/lib-storage/index/mbox/mbox-sync-parse.c @@ -218,6 +218,7 @@ static int parse_x_uid(struct mbox_sync_mail_context *ctx, } ctx->hdr_pos[MBOX_HDR_X_UID] = str_len(ctx->header); + ctx->parsed_uid = value; parse_trailing_whitespace(ctx, hdr); return TRUE; } @@ -355,12 +356,6 @@ void mbox_sync_parse_next_mail(struct istream *input, /* update uid-last field in X-IMAPbase */ ctx->need_rewrite = TRUE; } - if (ctx->mail.uid == 0 && !rewriting) { - /* missing X-UID */ - ctx->need_rewrite = TRUE; - ctx->mail.uid = sync_ctx->next_uid++; - sync_ctx->prev_msg_uid = ctx->mail.uid; - } ctx->body_offset = input->v_offset; } diff --git a/src/lib-storage/index/mbox/mbox-sync-private.h b/src/lib-storage/index/mbox/mbox-sync-private.h index 1728efb1f5..cbfdc14008 100644 --- a/src/lib-storage/index/mbox/mbox-sync-private.h +++ b/src/lib-storage/index/mbox/mbox-sync-private.h @@ -59,6 +59,7 @@ struct mbox_sync_mail_context { uoff_t content_length; size_t hdr_pos[MBOX_HDR_COUNT]; + uint32_t parsed_uid; unsigned int have_eoh:1; unsigned int need_rewrite:1; diff --git a/src/lib-storage/index/mbox/mbox-sync-update.c b/src/lib-storage/index/mbox/mbox-sync-update.c index 89a569a204..519f534385 100644 --- a/src/lib-storage/index/mbox/mbox-sync-update.c +++ b/src/lib-storage/index/mbox/mbox-sync-update.c @@ -207,11 +207,31 @@ static void mbox_sync_update_xkeywords(struct mbox_sync_mail_context *ctx) { } +static void mbox_sync_update_line(struct mbox_sync_mail_context *ctx, + size_t pos, string_t *new_line) +{ + const char *hdr, *p; + + if (ctx->header_first_change > pos) + ctx->header_first_change = pos; + + hdr = str_c(ctx->header) + pos; + p = strchr(hdr, '\n'); + + if (p == NULL) { + /* shouldn't really happen, but allow anyway.. */ + ctx->header_last_change = (size_t)-1; + str_truncate(ctx->header, pos); + str_append_str(ctx->header, new_line); + } else { + mbox_sync_move_buffer(ctx, pos, str_len(new_line), p - hdr + 1); + buffer_copy(ctx->header, pos, new_line, 0, (size_t)-1); + } +} + static void mbox_sync_update_x_imap_base(struct mbox_sync_mail_context *ctx) { string_t *str; - const char *p, *hdr; - size_t pos; if (!ctx->sync_ctx->dest_first_mail || ctx->hdr_pos[MBOX_HDR_X_IMAPBASE] == (size_t)-1 || @@ -219,31 +239,31 @@ static void mbox_sync_update_x_imap_base(struct mbox_sync_mail_context *ctx) ctx->sync_ctx->update_base_uid_last < ctx->sync_ctx->base_uid_last) return; - pos = ctx->hdr_pos[MBOX_HDR_X_IMAPBASE]; - if (ctx->header_first_change > pos) - ctx->header_first_change = pos; - /* update uid-last field in X-IMAPbase */ t_push(); + str = t_str_new(200); str_printfa(str, "%u %010u", ctx->sync_ctx->base_uid_validity, ctx->sync_ctx->update_base_uid_last); //FIXME:keywords_append(ctx, all_keywords); str_append_c(str, '\n'); - hdr = str_c(ctx->header) + pos; - p = strchr(hdr, '\n'); + mbox_sync_update_line(ctx, ctx->hdr_pos[MBOX_HDR_X_IMAPBASE], str); + t_pop(); +} - if (p == NULL) { - /* shouldn't really happen, but allow anyway.. */ - ctx->header_last_change = (size_t)-1; - str_truncate(ctx->header, pos); - str_append_str(ctx->header, str); - } else { - mbox_sync_move_buffer(ctx, pos, str_len(str), p - hdr + 1); - buffer_copy(ctx->header, pos, str, 0, (size_t)-1); - } +static void mbox_sync_update_x_uid(struct mbox_sync_mail_context *ctx) +{ + string_t *str; + + if (ctx->hdr_pos[MBOX_HDR_X_UID] == (size_t)-1 || + ctx->mail.uid == ctx->parsed_uid) + return; + t_push(); + str = t_str_new(64); + str_printfa(str, "%u", ctx->mail.uid); + mbox_sync_update_line(ctx, ctx->hdr_pos[MBOX_HDR_X_UID], str); t_pop(); } @@ -288,6 +308,7 @@ void mbox_sync_update_header(struct mbox_sync_mail_context *ctx, } mbox_sync_update_x_imap_base(ctx); + mbox_sync_update_x_uid(ctx); mbox_sync_add_missing_headers(ctx); ctx->updated = TRUE; } @@ -321,5 +342,6 @@ void mbox_sync_update_header_from(struct mbox_sync_mail_context *ctx, ctx->mail.uid = mail->uid; mbox_sync_update_x_imap_base(ctx); + mbox_sync_update_x_uid(ctx); mbox_sync_add_missing_headers(ctx); } diff --git a/src/lib-storage/index/mbox/mbox-sync.c b/src/lib-storage/index/mbox/mbox-sync.c index 7aa692bced..47d499ad7b 100644 --- a/src/lib-storage/index/mbox/mbox-sync.c +++ b/src/lib-storage/index/mbox/mbox-sync.c @@ -256,6 +256,11 @@ static int mbox_sync_read_index_syncs(struct mbox_sync_context *sync_ctx, if (sync_ctx->ibox->mbox_readonly || sync_ctx->index_sync_ctx == NULL) return 0; + if (uid == 0) { + /* nothing for this or the future ones */ + uid = (uint32_t)-1; + } + mbox_sync_buffer_delete_old(sync_ctx->syncs, uid); while (uid >= sync_rec->uid1) { if (uid <= sync_rec->uid2 && @@ -315,11 +320,13 @@ mbox_sync_read_index_rec(struct mbox_sync_context *sync_ctx, { const struct mail_index_record *rec = NULL; uint32_t messages_count; + int ret = 0; messages_count = mail_index_view_get_message_count(sync_ctx->sync_view); while (sync_ctx->idx_seq < messages_count) { - if (mail_index_lookup(sync_ctx->sync_view, - ++sync_ctx->idx_seq, &rec) < 0) { + ret = mail_index_lookup(sync_ctx->sync_view, + ++sync_ctx->idx_seq, &rec); + if (ret < 0) { mail_storage_set_index_error(sync_ctx->ibox); return -1; } @@ -342,7 +349,7 @@ mbox_sync_read_index_rec(struct mbox_sync_context *sync_ctx, } *rec_r = rec; - return 0; + return ret; } static int mbox_sync_get_from_offset(struct mbox_sync_context *sync_ctx, @@ -726,6 +733,24 @@ static int mbox_sync_loop(struct mbox_sync_context *sync_ctx, if (mbox_sync_read_index_syncs(sync_ctx, uid, &expunged) < 0) return -1; + if (uid != 0) { + ret = mbox_sync_read_index_rec(sync_ctx, uid, &rec); + if (ret < 0) + return -1; + if (ret == 0 && uid < sync_ctx->hdr->next_uid) { + /* this UID was already in index and it was + expunged */ + uid = 0; + } + } + if (uid == 0) { + /* missing/broken X-UID */ + mail_ctx->need_rewrite = TRUE; + mail_ctx->mail.uid = sync_ctx->next_uid++; + sync_ctx->prev_msg_uid = mail_ctx->mail.uid; + rec = NULL; + } + if (!expunged) { ret = mbox_sync_handle_header(mail_ctx); sync_ctx->dest_first_mail = FALSE; @@ -738,9 +763,6 @@ static int mbox_sync_loop(struct mbox_sync_context *sync_ctx, return ret; } - if (mbox_sync_read_index_rec(sync_ctx, uid, &rec) < 0) - return -1; - if (!expunged) { if (mbox_sync_update_index(sync_ctx, &mail_ctx->mail, rec) < 0)