Пример #1
0
static void maildir_mail_remove_sizes_from_uidlist(struct mail *mail)
{
	struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;

	if (maildir_uidlist_lookup_ext(mbox->uidlist, mail->uid,
				       MAILDIR_UIDLIST_REC_EXT_VSIZE) != NULL) {
		maildir_uidlist_unset_ext(mbox->uidlist, mail->uid,
					  MAILDIR_UIDLIST_REC_EXT_VSIZE);
	}
	if (maildir_uidlist_lookup_ext(mbox->uidlist, mail->uid,
				       MAILDIR_UIDLIST_REC_EXT_PSIZE) != NULL) {
		maildir_uidlist_unset_ext(mbox->uidlist, mail->uid,
					  MAILDIR_UIDLIST_REC_EXT_PSIZE);
	}
}
Пример #2
0
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;
}
Пример #3
0
static int maildir_quick_size_lookup(struct index_mail *mail, bool vsize,
				     uoff_t *size_r)
{
	struct mail *_mail = &mail->mail.mail;
	struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
	enum maildir_uidlist_rec_ext_key key;
	const char *path, *fname, *value;

	if (!_mail->saving) {
		if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0)
			return -1;
	} else {
		if (maildir_save_file_get_size(_mail->transaction, _mail->seq,
					       vsize, size_r) == 0)
			return 1;

		path = maildir_save_file_get_path(_mail->transaction,
						  _mail->seq);
		fname = strrchr(path, '/');
		fname = fname != NULL ? fname + 1 : path;
	}

	/* size can be included in filename */
	if (vsize || !mbox->storage->set->maildir_broken_filename_sizes) {
		if (maildir_filename_get_size(fname,
				vsize ? MAILDIR_EXTRA_VIRTUAL_SIZE :
					MAILDIR_EXTRA_FILE_SIZE, size_r))
			return 1;
	}

	/* size can be included in uidlist entry */
	if (!_mail->saving) {
		key = vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE :
			MAILDIR_UIDLIST_REC_EXT_PSIZE;
		value = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
						   key);
		if (value != NULL && str_to_uoff(value, size_r) == 0)
			return 1;
	}
	return 0;
}
Пример #4
0
static int
maildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
			 const char **value_r)
{
	struct index_mail *mail = (struct index_mail *)_mail;
	struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
	const char *path, *fname = NULL, *end, *guid, *uidl, *order;
	struct stat st;

	switch (field) {
	case MAIL_FETCH_GUID:
		/* use GUID from uidlist if it exists */
		i_assert(!_mail->saving);

		if (mail->data.guid != NULL) {
			*value_r = mail->data.guid;
			return 0;
		}

		/* first make sure that we have a refreshed uidlist */
		if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0)
			return -1;

		guid = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
						  MAILDIR_UIDLIST_REC_EXT_GUID);
		if (guid != NULL) {
			if (*guid != '\0') {
				*value_r = mail->data.guid =
					p_strdup(mail->mail.data_pool, guid);
				return 0;
			}

			mail_storage_set_critical(_mail->box->storage,
				"Maildir %s: Corrupted dovecot-uidlist: "
				"UID %u had empty GUID, clearing it",
				mailbox_get_path(_mail->box), _mail->uid);
			maildir_uidlist_unset_ext(mbox->uidlist, _mail->uid,
				MAILDIR_UIDLIST_REC_EXT_GUID);
		}

		/* default to base filename: */
		if (maildir_mail_get_special(_mail, MAIL_FETCH_STORAGE_ID,
					     value_r) < 0)
			return -1;
		mail->data.guid = mail->data.filename;
		return 0;
	case MAIL_FETCH_STORAGE_ID:
		if (mail->data.filename != NULL) {
			*value_r = mail->data.filename;
			return 0;
		}
		if (fname != NULL) {
			/* we came here from MAIL_FETCH_GUID,
			   avoid a second lookup */
		} else if (!_mail->saving) {
			if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0)
				return -1;
		} else {
			path = maildir_save_file_get_path(_mail->transaction,
							  _mail->seq);
			fname = strrchr(path, '/');
			fname = fname != NULL ? fname + 1 : path;
		}
		end = strchr(fname, MAILDIR_INFO_SEP);
		mail->data.filename = end == NULL ?
			p_strdup(mail->mail.data_pool, fname) :
			p_strdup_until(mail->mail.data_pool, fname, end);
		*value_r = mail->data.filename;
		return 0;
	case MAIL_FETCH_UIDL_BACKEND:
		uidl = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
					MAILDIR_UIDLIST_REC_EXT_POP3_UIDL);
		if (uidl == NULL) {
			/* use the default */
			*value_r = "";
		} else if (*uidl == '\0') {
			/* special optimization case: use the base file name */
			return maildir_mail_get_special(_mail,
					MAIL_FETCH_STORAGE_ID, value_r);
		} else {
			*value_r = p_strdup(mail->mail.data_pool, uidl);
		}
		return 0;
	case MAIL_FETCH_POP3_ORDER:
		order = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
					MAILDIR_UIDLIST_REC_EXT_POP3_ORDER);
		if (order == NULL) {
			*value_r = "";
		} else {
			*value_r = p_strdup(mail->mail.data_pool, order);
		}
		return 0;
	case MAIL_FETCH_REFCOUNT:
		if (maildir_mail_stat(_mail, &st) < 0)
			return -1;
		*value_r = p_strdup_printf(mail->mail.data_pool, "%lu",
					   (unsigned long)st.st_nlink);
		return 0;
	default:
		return index_mail_get_special(_mail, field, value_r);
	}
}