コード例 #1
0
ファイル: mbox-save.c プロジェクト: via/dovecot-clouddb
static void
mbox_save_append_keyword_headers(struct mbox_save_context *ctx,
				 struct mail_keywords *keywords)
{
	unsigned char space[MBOX_HEADER_PADDING+1 +
			    sizeof("Content-Length: \n")-1 + MAX_INT_STRLEN];
	const ARRAY_TYPE(keywords) *keyword_names_list;
	const char *const *keyword_names;
	unsigned int i, count, keyword_names_count;

	keyword_names_list = mail_index_get_keywords(ctx->mbox->box.index);
	keyword_names = array_get(keyword_names_list, &keyword_names_count);

	str_append(ctx->headers, "X-Keywords:");
	count = keywords == NULL ? 0 : keywords->count;
	for (i = 0; i < count; i++) {
		i_assert(keywords->idx[i] < keyword_names_count);

		str_append_c(ctx->headers, ' ');
		str_append(ctx->headers, keyword_names[keywords->idx[i]]);
	}

	memset(space, ' ', sizeof(space));
	str_append_n(ctx->headers, space, sizeof(space));
	ctx->space_end_idx = str_len(ctx->headers);
	str_append_c(ctx->headers, '\n');
}
コード例 #2
0
ファイル: maildir-keywords.c プロジェクト: bsmr-dovecot/core
struct maildir_keywords_sync_ctx *
maildir_keywords_sync_init(struct maildir_keywords *mk,
			   struct mail_index *index)
{
	struct maildir_keywords_sync_ctx *ctx;

	ctx = i_new(struct maildir_keywords_sync_ctx, 1);
	ctx->mk = mk;
	ctx->index = index;
	ctx->keywords = mail_index_get_keywords(index);
	i_array_init(&ctx->idx_to_chr, MAILDIR_MAX_KEYWORDS);
	return ctx;
}
コード例 #3
0
ファイル: index-status.c プロジェクト: via/dovecot-clouddb
void index_storage_get_status(struct mailbox *box,
			      enum mailbox_status_items items,
			      struct mailbox_status *status_r)
{
	const struct mail_index_header *hdr;

	i_assert(box->opened);

	memset(status_r, 0, sizeof(struct mailbox_status));

	/* we can get most of the status items without any trouble */
	hdr = mail_index_get_header(box->view);
	status_r->messages = hdr->messages_count;
	if ((items & STATUS_RECENT) != 0) {
		status_r->recent = index_mailbox_get_recent_count(box);
		i_assert(status_r->recent <= status_r->messages);
	}
	status_r->unseen = hdr->messages_count - hdr->seen_messages_count;
	status_r->uidvalidity = hdr->uid_validity;
	status_r->uidnext = hdr->next_uid;
	status_r->nonpermanent_modseqs = mail_index_is_in_memory(box->index);
	if ((items & STATUS_HIGHESTMODSEQ) != 0) {
		status_r->highest_modseq =
			mail_index_modseq_get_highest(box->view);
		if (status_r->highest_modseq == 0) {
			/* modseqs not enabled yet, but we can't return 0 */
			status_r->highest_modseq = 1;
		}
	}

	if ((items & STATUS_FIRST_UNSEEN_SEQ) != 0) {
		mail_index_lookup_first(box->view, 0, MAIL_SEEN,
					&status_r->first_unseen_seq);
	}

	if ((items & STATUS_KEYWORDS) != 0)
		status_r->keywords = mail_index_get_keywords(box->index);
	if ((items & STATUS_CACHE_FIELDS) != 0)
		index_storage_get_status_cache_fields(box, status_r);
	if ((items & STATUS_VIRTUAL_SIZE) != 0)
		index_storage_get_status_virtual_size(box, status_r);
}
コード例 #4
0
ファイル: antispam-storage-1.2.c プロジェクト: flant/LMPD
static void
antispam_mail_update_keywords(struct mail *mail,
			      enum modify_type modify_type,
			      struct mail_keywords *keywords)
{
	struct mail_private *pmail = (struct mail_private *)mail;
	union mail_module_context *amail = ANTISPAM_MAIL_CONTEXT(pmail);
	unsigned int i, numkwds;
	const ARRAY_TYPE(keywords) *idxkwd = mail_index_get_keywords(keywords->index);
	const char *const *keyword_names = array_get(idxkwd, &numkwds);
	const char *const *orig_keywords;
	bool previous_spam_keyword, now_spam_keyword;

	switch (modify_type) {
	case MODIFY_ADD:
		debug("adding keyword(s)\n");
		break;
	case MODIFY_REMOVE:
		debug("removing keyword(s)\n");
		break;
	case MODIFY_REPLACE:
		debug("replacing keyword(s)\n");
		break;
	default:
		i_assert(0);
	}

	orig_keywords = pmail->v.get_keywords(mail);
	if (orig_keywords) {
		debug("original keyword list:\n");
		while (*orig_keywords) {
			debug(" * %s\n", *orig_keywords);
			if (keyword_is_spam(*orig_keywords))
				previous_spam_keyword = TRUE;
			orig_keywords++;
		}
	}

	debug("keyword list:\n");

	for (i = 0; i < keywords->count; i++) {
		unsigned int idx = keywords->idx[i];

		i_assert(idx < numkwds);

		debug(" * %s\n", keyword_names[idx]);

		switch (modify_type) {
		case MODIFY_ADD:
		case MODIFY_REPLACE:
			if (keyword_is_spam(keyword_names[idx]))
				now_spam_keyword = TRUE;
			break;
		case MODIFY_REMOVE:
			if (keyword_is_spam(keyword_names[idx]))
				now_spam_keyword = FALSE;
			break;
		default:
			i_assert(0);
		}
	}

	amail->super.update_keywords(mail, modify_type, keywords);

	debug("previous-spam, now-spam: %d, %d\n",
	      previous_spam_keyword, now_spam_keyword);

	if (previous_spam_keyword != now_spam_keyword) {
		/*
		 * Call backend here.
		 *
		 * TODO: It is not clear how to roll back the
		 *       keyword change if the backend fails.
		 */
	}
}
コード例 #5
0
void index_storage_get_open_status(struct mailbox *box,
				   enum mailbox_status_items items,
				   struct mailbox_status *status_r)
{
	const struct mail_index_header *hdr;

	/* we can get most of the status items without any trouble */
	hdr = mail_index_get_header(box->view);
	status_r->messages = hdr->messages_count;
	if ((items & STATUS_RECENT) != 0) {
		if ((box->flags & MAILBOX_FLAG_DROP_RECENT) != 0) {
			/* recent flags are set and dropped by the previous
			   sync while index was locked. if we updated the
			   recent flags here we'd have a race condition. */
			i_assert(box->synced);
		} else {
			/* make sure recent count is set, in case we haven't
			   synced yet */
			index_sync_update_recent_count(box);
		}
		status_r->recent = index_mailbox_get_recent_count(box);
		i_assert(status_r->recent <= status_r->messages);
	}
	if ((items & STATUS_UNSEEN) != 0) {
		if (box->view_pvt == NULL ||
		    (mailbox_get_private_flags_mask(box) & MAIL_SEEN) == 0) {
			status_r->unseen = hdr->messages_count -
				hdr->seen_messages_count;
		} else {
			status_r->unseen = index_storage_count_pvt_unseen(box);
		}
	}
	status_r->uidvalidity = hdr->uid_validity;
	status_r->uidnext = hdr->next_uid;
	status_r->first_recent_uid = hdr->first_recent_uid;
	if ((items & STATUS_HIGHESTMODSEQ) != 0) {
		status_r->nonpermanent_modseqs =
			mail_index_is_in_memory(box->index);
		status_r->no_modseq_tracking =
			!mail_index_have_modseq_tracking(box->index);
		status_r->highest_modseq =
			mail_index_modseq_get_highest(box->view);
		if (status_r->highest_modseq == 0) {
			/* modseqs not enabled yet, but we can't return 0 */
			status_r->highest_modseq = 1;
		}
	}
	if ((items & STATUS_HIGHESTPVTMODSEQ) != 0 && box->view_pvt != NULL) {
		status_r->highest_pvt_modseq =
			mail_index_modseq_get_highest(box->view_pvt);
		if (status_r->highest_pvt_modseq == 0) {
			/* modseqs not enabled yet, but we can't return 0 */
			status_r->highest_pvt_modseq = 1;
		}
	}

	if ((items & STATUS_FIRST_UNSEEN_SEQ) != 0) {
		if (box->view_pvt == NULL ||
		    (mailbox_get_private_flags_mask(box) & MAIL_SEEN) == 0) {
			mail_index_lookup_first(box->view, 0, MAIL_SEEN,
						&status_r->first_unseen_seq);
		} else {
			status_r->first_unseen_seq =
				index_storage_find_first_pvt_unseen_seq(box);
		}
	}
	if ((items & STATUS_LAST_CACHED_SEQ) != 0)
		get_last_cached_seq(box, &status_r->last_cached_seq);

	if ((items & STATUS_KEYWORDS) != 0)
		status_r->keywords = mail_index_get_keywords(box->index);
	if ((items & STATUS_PERMANENT_FLAGS) != 0) {
		if (!mailbox_is_readonly(box)) {
			status_r->permanent_flags = MAIL_FLAGS_NONRECENT;
			status_r->permanent_keywords = TRUE;
			status_r->allow_new_keywords =
				!box->disallow_new_keywords;
		}
	}
}
コード例 #6
0
bool mail_search_arg_to_imap(string_t *dest, const struct mail_search_arg *arg,
			     const char **error_r)
{
	unsigned int start_pos;

	if (arg->match_not)
		str_append(dest, "NOT ");
	start_pos = str_len(dest);
	switch (arg->type) {
	case SEARCH_OR:
		if (!mail_search_subargs_to_imap(dest, arg->value.subargs,
						 "OR ", error_r))
			return FALSE;
		break;
	case SEARCH_SUB:
		if (!mail_search_subargs_to_imap(dest, arg->value.subargs,
						 "", error_r))
			return FALSE;
		break;
	case SEARCH_ALL:
		str_append(dest, "ALL");
		break;
	case SEARCH_SEQSET:
		imap_write_seq_range(dest, &arg->value.seqset);
		break;
	case SEARCH_UIDSET:
		str_append(dest, "UID ");
		imap_write_seq_range(dest, &arg->value.seqset);
		break;
	case SEARCH_FLAGS:
		i_assert((arg->value.flags & MAIL_FLAGS_MASK) != 0);
		str_append_c(dest, '(');
		if ((arg->value.flags & MAIL_ANSWERED) != 0)
			str_append(dest, "ANSWERED ");
		if ((arg->value.flags & MAIL_FLAGGED) != 0)
			str_append(dest, "FLAGGED ");
		if ((arg->value.flags & MAIL_DELETED) != 0)
			str_append(dest, "DELETED ");
		if ((arg->value.flags & MAIL_SEEN) != 0)
			str_append(dest, "SEEN ");
		if ((arg->value.flags & MAIL_DRAFT) != 0)
			str_append(dest, "DRAFT ");
		if ((arg->value.flags & MAIL_RECENT) != 0)
			str_append(dest, "RECENT ");
		str_truncate(dest, str_len(dest)-1);
		str_append_c(dest, ')');
		break;
	case SEARCH_KEYWORDS: {
		const struct mail_keywords *kw = arg->value.keywords;
		const ARRAY_TYPE(keywords) *names_arr;
		const char *const *namep;
		unsigned int i;

		if (kw == NULL) {
			/* uninitialized */
			str_printfa(dest, "KEYWORD %s", arg->value.str);
			break;
		}

		names_arr = mail_index_get_keywords(kw->index);

		str_append_c(dest, '(');
		for (i = 0; i < kw->count; i++) {
			namep = array_idx(names_arr, kw->idx[i]);
			if (i > 0)
				str_append_c(dest, ' ');
			str_printfa(dest, "KEYWORD %s", *namep);
		}
		str_append_c(dest, ')');
		break;
	}

	case SEARCH_BEFORE:
		switch (arg->value.date_type) {
		case MAIL_SEARCH_DATE_TYPE_SENT:
			str_append(dest, "SENTBEFORE");
			break;
		case MAIL_SEARCH_DATE_TYPE_RECEIVED:
			str_append(dest, "BEFORE");
			break;
		case MAIL_SEARCH_DATE_TYPE_SAVED:
			str_append(dest, "X-SAVEDBEFORE");
			break;
		}
		if (mail_search_arg_to_imap_date(dest, arg))
			;
		else if (arg->value.date_type != MAIL_SEARCH_DATE_TYPE_RECEIVED ||
			 arg->value.time > ioloop_time) {
			*error_r = t_strdup_printf(
				"SEARCH_BEFORE can't be written as IMAP for timestamp %ld (type=%d, use_tz=%d)",
				(long)arg->value.time, arg->value.date_type,
				(arg->value.search_flags & MAIL_SEARCH_ARG_FLAG_USE_TZ) != 0);
			return FALSE;
		} else {
			str_truncate(dest, start_pos);
			str_printfa(dest, "OLDER %u",
				    (unsigned int)(ioloop_time - arg->value.time + 1));
		}
		break;
	case SEARCH_ON:
		switch (arg->value.date_type) {
		case MAIL_SEARCH_DATE_TYPE_SENT:
			str_append(dest, "SENTON");
			break;
		case MAIL_SEARCH_DATE_TYPE_RECEIVED:
			str_append(dest, "ON");
			break;
		case MAIL_SEARCH_DATE_TYPE_SAVED:
			str_append(dest, "X-SAVEDON");
			break;
		}
		if (!mail_search_arg_to_imap_date(dest, arg)) {
			*error_r = t_strdup_printf(
				"SEARCH_ON can't be written as IMAP for timestamp %ld (type=%d, use_tz=%d)",
				(long)arg->value.time, arg->value.date_type,
				(arg->value.search_flags & MAIL_SEARCH_ARG_FLAG_USE_TZ) != 0);
			return FALSE;
		}
		break;
	case SEARCH_SINCE:
		switch (arg->value.date_type) {
		case MAIL_SEARCH_DATE_TYPE_SENT:
			str_append(dest, "SENTSINCE");
			break;
		case MAIL_SEARCH_DATE_TYPE_RECEIVED:
			str_append(dest, "SINCE");
			break;
		case MAIL_SEARCH_DATE_TYPE_SAVED:
			str_append(dest, "X-SAVEDSINCE");
			break;
		}
		if (mail_search_arg_to_imap_date(dest, arg))
			;
		else if (arg->value.date_type != MAIL_SEARCH_DATE_TYPE_RECEIVED ||
			 arg->value.time >= ioloop_time) {
			*error_r = t_strdup_printf(
				"SEARCH_SINCE can't be written as IMAP for timestamp %ld (type=%d, use_tz=%d)",
				(long)arg->value.time, arg->value.date_type,
				(arg->value.search_flags & MAIL_SEARCH_ARG_FLAG_USE_TZ) != 0);
			return FALSE;
		} else {
			str_truncate(dest, start_pos);
			str_printfa(dest, "YOUNGER %u",
				    (unsigned int)(ioloop_time - arg->value.time));
		}
		break;
	case SEARCH_SMALLER:
		str_printfa(dest, "SMALLER %llu", (unsigned long long)arg->value.size);
		break;
	case SEARCH_LARGER:
		str_printfa(dest, "LARGER %llu", (unsigned long long)arg->value.size);
		break;
	case SEARCH_HEADER:
	case SEARCH_HEADER_ADDRESS:
	case SEARCH_HEADER_COMPRESS_LWSP:
		if (strcasecmp(arg->hdr_field_name, "From") == 0 ||
		    strcasecmp(arg->hdr_field_name, "To") == 0 ||
		    strcasecmp(arg->hdr_field_name, "Cc") == 0 ||
		    strcasecmp(arg->hdr_field_name, "Bcc") == 0 ||
		    strcasecmp(arg->hdr_field_name, "Subject") == 0)
			str_append(dest, t_str_ucase(arg->hdr_field_name));
		else {
			str_append(dest, "HEADER ");
			imap_append_astring(dest, arg->hdr_field_name);
		}
		str_append_c(dest, ' ');
		imap_append_astring(dest, arg->value.str);
		break;

	case SEARCH_BODY:
		str_append(dest, "BODY ");
		imap_append_astring(dest, arg->value.str);
		break;
	case SEARCH_TEXT:
		str_append(dest, "TEXT ");
		imap_append_astring(dest, arg->value.str);
		break;

	/* extensions */
	case SEARCH_MODSEQ: {
		bool extended_output = FALSE;

		str_append(dest, "MODSEQ ");
		if (arg->value.str != NULL) {
			str_printfa(dest, "/flags/%s", arg->value.str);
			extended_output = TRUE;
		} else if (arg->value.flags != 0) {
			str_append(dest, "/flags/");
			imap_write_flags(dest, arg->value.flags, NULL);
			extended_output = TRUE;
		}
		if (extended_output) {
			str_append_c(dest, ' ');
			switch (arg->value.modseq->type) {
			case MAIL_SEARCH_MODSEQ_TYPE_ANY:
				str_append(dest, "all");
				break;
			case MAIL_SEARCH_MODSEQ_TYPE_PRIVATE:
				str_append(dest, "priv");
				break;
			case MAIL_SEARCH_MODSEQ_TYPE_SHARED:
				str_append(dest, "shared");
				break;
			}
			str_append_c(dest, ' ');
		}
		str_printfa(dest, "%llu", (unsigned long long)arg->value.modseq->modseq);
		break;
	}
	case SEARCH_INTHREAD:
		str_append(dest, "INTHREAD ");
		imap_append_astring(dest, mail_thread_type_to_str(arg->value.thread_type));
		str_append_c(dest, ' ');
		if (!mail_search_subargs_to_imap(dest, arg->value.subargs,
						 "", error_r))
			return FALSE;
		break;
	case SEARCH_GUID:
		str_append(dest, "X-GUID ");
		imap_append_astring(dest, arg->value.str);
		break;
	case SEARCH_MAILBOX:
		*error_r = "SEARCH_MAILBOX can't be written as IMAP";
		return FALSE;
	case SEARCH_MAILBOX_GUID:
		*error_r = "SEARCH_MAILBOX_GUID can't be written as IMAP";
		return FALSE;
	case SEARCH_MAILBOX_GLOB:
		str_append(dest, "X-MAILBOX ");
		imap_append_astring(dest, arg->value.str);
		break;
	case SEARCH_REAL_UID:
		str_append(dest, "X-REAL-UID ");
		imap_write_seq_range(dest, &arg->value.seqset);
		break;
	}
	return TRUE;
}
コード例 #7
0
ファイル: index-storage.c プロジェクト: Distrotech/dovecot
int index_storage_mailbox_open(struct mailbox *box, bool move_to_memory)
{
	struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
	enum mail_index_open_flags index_flags;
	int ret;

	i_assert(!box->opened);

	index_flags = ibox->index_flags;
	if (move_to_memory)
		ibox->index_flags &= ~MAIL_INDEX_OPEN_FLAG_CREATE;

	if (index_storage_mailbox_alloc_index(box) < 0)
		return -1;

	/* make sure mail_index_set_permissions() has been called */
	(void)mailbox_get_permissions(box);

	ret = mail_index_open(box->index, index_flags);
	if (ret <= 0 || move_to_memory) {
		if ((index_flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) != 0) {
			i_assert(ret <= 0);
			mailbox_set_index_error(box);
			return -1;
		}

		if (mail_index_move_to_memory(box->index) < 0) {
			/* try opening once more. it should be created
			   directly into memory now. */
			if (mail_index_open_or_create(box->index,
						      index_flags) < 0)
				i_panic("in-memory index creation failed");
		}
	}
	if ((index_flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) != 0) {
		if (mail_index_is_in_memory(box->index)) {
			mail_storage_set_critical(box->storage,
				"Couldn't create index file");
			mail_index_close(box->index);
			return -1;
		}
	}

	if ((box->flags & MAILBOX_FLAG_OPEN_DELETED) == 0) {
		if (mail_index_is_deleted(box->index)) {
			mailbox_set_deleted(box);
			mail_index_close(box->index);
			return -1;
		}
	}

	box->cache = mail_index_get_cache(box->index);
	index_cache_register_defaults(box);
	box->view = mail_index_view_open(box->index);
	ibox->keyword_names = mail_index_get_keywords(box->index);
	ibox->vsize_hdr_ext_id =
		mail_index_ext_register(box->index, "hdr-vsize",
					sizeof(struct index_vsize_header), 0,
					sizeof(uint64_t));

	box->opened = TRUE;

	if ((box->enabled_features & MAILBOX_FEATURE_CONDSTORE) != 0)
		mail_index_modseq_enable(box->index);

	index_thread_mailbox_opened(box);
	hook_mailbox_opened(box);
	return 0;
}