static bool
maildir_expunge_is_valid_guid(struct maildir_index_sync_context *ctx,
			      uint32_t uid, const char *filename,
			      guid_128_t expunged_guid_128)
{
	guid_128_t guid_128;
	const char *guid;

	if (guid_128_is_empty(expunged_guid_128)) {
		/* no GUID associated with expunge */
		return TRUE;
	}

	T_BEGIN {
		guid = maildir_uidlist_lookup_ext(ctx->mbox->uidlist, uid,
						  MAILDIR_UIDLIST_REC_EXT_GUID);
		if (guid == NULL)
			guid = t_strcut(filename, ':');
		mail_generate_guid_128_hash(guid, guid_128);
	} T_END;

	if (memcmp(guid_128, expunged_guid_128, sizeof(guid_128)) == 0)
		return TRUE;

	mail_storage_set_critical(&ctx->mbox->storage->storage,
		"Mailbox %s: Expunged GUID mismatch for UID %u: %s vs %s",
		ctx->mbox->box.vname, ctx->uid,
		guid_128_to_string(guid_128),
		guid_128_to_string(expunged_guid_128));
	return FALSE;
}
Exemple #2
0
void dbox_save_write_metadata(struct mail_save_context *_ctx,
			      struct ostream *output, uoff_t output_msg_size,
			      const char *orig_mailbox_name,
			      guid_128_t guid_128)
{
	struct dbox_save_context *ctx = (struct dbox_save_context *)_ctx;
	struct mail_save_data *mdata = &ctx->ctx.data;
	struct dbox_metadata_header metadata_hdr;
	const char *guid;
	string_t *str;
	uoff_t vsize;

	memset(&metadata_hdr, 0, sizeof(metadata_hdr));
	memcpy(metadata_hdr.magic_post, DBOX_MAGIC_POST,
	       sizeof(metadata_hdr.magic_post));
	o_stream_nsend(output, &metadata_hdr, sizeof(metadata_hdr));

	str = t_str_new(256);
	if (output_msg_size != ctx->input->v_offset) {
		/* a plugin changed the data written to disk, so the
		   "message size" dbox header doesn't contain the actual
		   "physical" message size. we need to save it as a
		   separate metadata header. */
		str_printfa(str, "%c%llx\n", DBOX_METADATA_PHYSICAL_SIZE,
			    (unsigned long long)ctx->input->v_offset);
	}
	str_printfa(str, "%c%lx\n", DBOX_METADATA_RECEIVED_TIME,
		    (unsigned long)mdata->received_date);
	if (mail_get_virtual_size(_ctx->dest_mail, &vsize) < 0)
		i_unreached();
	str_printfa(str, "%c%llx\n", DBOX_METADATA_VIRTUAL_SIZE,
		    (unsigned long long)vsize);
	if (mdata->pop3_uidl != NULL) {
		i_assert(strchr(mdata->pop3_uidl, '\n') == NULL);
		str_printfa(str, "%c%s\n", DBOX_METADATA_POP3_UIDL,
			    mdata->pop3_uidl);
	}

	guid = mdata->guid;
	if (guid != NULL)
		mail_generate_guid_128_hash(guid, guid_128);
	else {
		guid_128_generate(guid_128);
		guid = guid_128_to_string(guid_128);
	}
	str_printfa(str, "%c%s\n", DBOX_METADATA_GUID, guid);

	if (orig_mailbox_name != NULL &&
	    strchr(orig_mailbox_name, '\r') == NULL &&
	    strchr(orig_mailbox_name, '\n') == NULL) {
		/* save the original mailbox name so if mailbox indexes get
		   corrupted we can place at least some (hopefully most) of
		   the messages to correct mailboxes. */
		str_printfa(str, "%c%s\n", DBOX_METADATA_ORIG_MAILBOX,
			    orig_mailbox_name);
	}

	dbox_attachment_save_write_metadata(_ctx, str);

	str_append_c(str, '\n');
	o_stream_nsend(output, str_data(str), str_len(str));
}