Exemple #1
0
static struct mailbox *antispam_mailbox_open(struct mail_storage *storage,
        const char *name,
        struct istream *input,
        enum mailbox_open_flags flags)
{
    struct antispam_mail_storage *as_storage = ANTISPAM_CONTEXT(storage);
    struct mailbox *box;
    struct antispam_mailbox *asbox;

    box = as_storage->super.mailbox_open(storage, name, input, flags);
    if (box == NULL)
        return NULL;

    asbox = p_new(box->pool, struct antispam_mailbox, 1);
    asbox->super = box->v;
    asbox->save_hack = FALSE;
    asbox->movetype = MMT_APPEND;

    if (need_folder_hook) {
        /* override save_init to override want_mail, we need that */
        box->v.save_init = antispam_save_init;
        box->v.save_finish = antispam_save_finish;
        box->v.transaction_begin = antispam_mailbox_transaction_begin;
        box->v.transaction_commit = antispam_mailbox_transaction_commit;
        box->v.transaction_rollback = antispam_mailbox_transaction_rollback;
        box->v.copy = antispam_copy;
    }

    if (need_keyword_hook)
        box->v.mail_alloc = antispam_mailbox_mail_alloc;

    array_idx_set(&box->module_contexts, antispam_storage_module_id,
                  &asbox);
    return box;
}
Exemple #2
0
static struct mail *
antispam_mailbox_mail_alloc(struct mailbox_transaction_context *ctx,
                            enum mail_fetch_field wanted_fields,
                            struct mailbox_header_lookup_ctx *wanted_headers)
{
    struct antispam_mailbox *asbox = ANTISPAM_CONTEXT(ctx->box);
    struct antispam_mail *amail = i_new(struct antispam_mail, 1);
    struct mail_private *pmail;

    /* XXX: is this cast the right thing to do? */
    pmail = (struct mail_private *) asbox->super.mail_alloc(
                ctx,
                wanted_fields,
                wanted_headers);

    amail->super = pmail->v;

    array_idx_set(&pmail->module_contexts,
                  antispam_storage_module_id,
                  &amail);

    pmail->v.update_keywords = antispam_mail_update_keywords;
    pmail->v.free = antispam_mail_free;

    return (struct mail *)pmail;
}
void sieve_generator_extension_set_context
(struct sieve_generator *gentr, const struct sieve_extension *ext, void *context)
{
	if ( ext->id < 0 ) return;

	array_idx_set(&gentr->ext_contexts, (unsigned int) ext->id, &context);
}
static void
ext_reset_update_atomic(struct mail_index_transaction *t,
			uint32_t ext_id, uint32_t expected_reset_id)
{
	const struct mail_index_ext *map_ext;
	struct mail_transaction_ext_reset *reset;
	uint32_t idx, reset_id;

	if (!mail_index_map_get_ext_idx(t->view->index->map, ext_id, &idx)) {
		/* new extension */
		reset_id = 1;
	} else {
		map_ext = array_idx(&t->view->index->map->extensions, idx);
		reset_id = map_ext->reset_id + 1;
	}
	if (reset_id != expected_reset_id) {
		/* ignore this extension update */
		mail_index_ext_set_reset_id(t, ext_id, 0);
		return;
	}

	if (reset_id == 0)
		reset_id++;

	array_idx_set(&t->ext_reset_ids, ext_id, &reset_id);

	/* reseting existing data is optional */
	if (array_is_created(&t->ext_resets)) {
		reset = array_idx_modifiable(&t->ext_resets, ext_id);
		if (reset->new_reset_id == (uint32_t)-1)
			reset->new_reset_id = reset_id;
	}
}
Exemple #5
0
static void
mail_cache_compress_field(struct mail_cache_copy_context *ctx,
			  const struct mail_cache_iterate_field *field)
{
        struct mail_cache_field *cache_field;
	enum mail_cache_decision_type dec;
	uint32_t file_field_idx, size32;
	uint8_t *field_seen;

	file_field_idx = ctx->field_file_map[field->field_idx];
	if (file_field_idx == (uint32_t)-1)
		return;

	cache_field = &ctx->cache->fields[field->field_idx].field;

	field_seen = buffer_get_space_unsafe(ctx->field_seen,
					     field->field_idx, 1);
	if (*field_seen == ctx->field_seen_value) {
		/* duplicate */
		if (cache_field->type == MAIL_CACHE_FIELD_BITMASK)
			mail_cache_merge_bitmask(ctx, field);
		return;
	}
	*field_seen = ctx->field_seen_value;

	dec = cache_field->decision & ~MAIL_CACHE_DECISION_FORCED;
	if (ctx->new_msg) {
		if (dec == MAIL_CACHE_DECISION_NO)
			return;
	} else {
		if (dec != MAIL_CACHE_DECISION_YES)
			return;
	}

	buffer_append(ctx->buffer, &file_field_idx, sizeof(file_field_idx));

	if (cache_field->field_size == UINT_MAX) {
		size32 = (uint32_t)field->size;
		buffer_append(ctx->buffer, &size32, sizeof(size32));
	}

	if (cache_field->type == MAIL_CACHE_FIELD_BITMASK) {
		/* remember the position in case we need to update it */
		unsigned int pos = ctx->buffer->used;

		array_idx_set(&ctx->bitmask_pos, field->field_idx, &pos);
	}
	buffer_append(ctx->buffer, field->data, field->size);
	if ((field->size & 3) != 0)
		buffer_append_zero(ctx->buffer, 4 - (field->size & 3));
}
Exemple #6
0
static struct mailbox_transaction_context *
antispam_mailbox_transaction_begin(struct mailbox *box,
                                   enum mailbox_transaction_flags flags)
{
    struct antispam_mailbox *asbox = ANTISPAM_CONTEXT(box);
    struct mailbox_transaction_context *t;
    struct antispam_transaction_context *ast;

    t = asbox->super.transaction_begin(box, flags);
    ast = antispam_transaction_begin(box);

    array_idx_set(&t->module_contexts, antispam_storage_module_id, &ast);
    return t;
}
Exemple #7
0
void antispam_mail_storage_created(struct mail_storage *storage)
{
    struct antispam_mail_storage *as_storage;

    if (antispam_next_hook_mail_storage_created != NULL)
        antispam_next_hook_mail_storage_created(storage);

    as_storage = p_new(storage->pool, struct antispam_mail_storage, 1);
    as_storage->super = storage->v;
    storage->v.mailbox_open = antispam_mailbox_open;

    if (!antispam_storage_module_id_set) {
        antispam_storage_module_id = mail_storage_module_id++;
        antispam_storage_module_id_set = TRUE;
    }

    array_idx_set(&storage->module_contexts,
                  antispam_storage_module_id, &as_storage);
}
static void index_mail_parse_header_register_all_wanted(struct index_mail *mail)
{
	struct mail *_mail = &mail->mail.mail;
	const struct mail_cache_field *all_cache_fields;
	unsigned int i, count;

	all_cache_fields =
		mail_cache_register_get_list(_mail->box->cache,
					     pool_datastack_create(), &count);
	for (i = 0; i < count; i++) {
		if (strncasecmp(all_cache_fields[i].name, "hdr.", 4) != 0)
			continue;
		if (!mail_cache_field_want_add(_mail->transaction->cache_trans,
					       _mail->seq, i))
			continue;

		array_idx_set(&mail->header_match, all_cache_fields[i].idx,
			      &mail->header_match_value);
	}
}
static void index_mail_parse_header_finish(struct index_mail *mail)
{
	struct mail *_mail = &mail->mail.mail;
	const struct index_mail_line *lines;
	const unsigned char *header, *data;
	const uint8_t *match;
	buffer_t *buf;
	size_t data_size;
	unsigned int i, j, count, match_idx, match_count;
	bool noncontiguous;

	/* sort it first so fields are grouped together and ordered by
	   line number */
	array_sort(&mail->header_lines, header_line_cmp);

	lines = array_get(&mail->header_lines, &count);
	match = array_get(&mail->header_match, &match_count);
	header = buffer_get_data(mail->header_data, NULL);
	buf = buffer_create_dynamic(pool_datastack_create(), 256);

	/* go through all the header lines we found */
	for (i = match_idx = 0; i < count; i = j) {
		/* matches and header lines are both sorted, all matches
		   until lines[i] weren't found */
		while (match_idx < lines[i].field_idx &&
		       match_idx < match_count) {
			if (HEADER_MATCH_USABLE(mail, match[match_idx]) &&
			    mail_cache_field_can_add(_mail->transaction->cache_trans,
						     _mail->seq, match_idx)) {
				/* this header doesn't exist. remember that. */
				i_assert((match[match_idx] &
					  HEADER_MATCH_FLAG_FOUND) == 0);
				index_mail_cache_add_idx(mail, match_idx,
							 "", 0);
			}
			match_idx++;
		}

		if (match_idx < match_count) {
			/* save index to first header line */
			j = i + 1;
			array_idx_set(&mail->header_match_lines, match_idx, &j);
			match_idx++;
		}

		if (!mail_cache_field_can_add(_mail->transaction->cache_trans,
					      _mail->seq, lines[i].field_idx)) {
			/* header is already cached */
			j = i + 1;
			continue;
		}

		/* buffer contains: { uint32_t line_num[], 0, header texts }
		   noncontiguous is just a small optimization.. */
		buffer_set_used_size(buf, 0);
		buffer_append(buf, &lines[i].line_num,
			      sizeof(lines[i].line_num));

		noncontiguous = FALSE;
		for (j = i+1; j < count; j++) {
			if (lines[j].field_idx != lines[i].field_idx)
				break;

			if (lines[j].start_pos != lines[j-1].end_pos)
				noncontiguous = TRUE;
			buffer_append(buf, &lines[j].line_num,
				      sizeof(lines[j].line_num));
		}
		buffer_append_zero(buf, sizeof(uint32_t));

		if (noncontiguous) {
			for (; i < j; i++) {
				buffer_append(buf, header + lines[i].start_pos,
					      lines[i].end_pos -
					      lines[i].start_pos);
			}
			i--;
		} else {
			buffer_append(buf, header + lines[i].start_pos,
				      lines[j-1].end_pos - lines[i].start_pos);
		}

		data = buffer_get_data(buf, &data_size);
		index_mail_cache_add_idx(mail, lines[i].field_idx,
					 data, data_size);
	}

	for (; match_idx < match_count; match_idx++) {
		if (HEADER_MATCH_USABLE(mail, match[match_idx]) &&
		    mail_cache_field_can_add(_mail->transaction->cache_trans,
					     _mail->seq, match_idx)) {
			/* this header doesn't exist. remember that. */
			i_assert((match[match_idx] &
				  HEADER_MATCH_FLAG_FOUND) == 0);
			index_mail_cache_add_idx(mail, match_idx, "", 0);
		}
	}

	mail->data.dont_cache_field_idx = UINT_MAX;
}
void index_mail_parse_header_init(struct index_mail *mail,
				  struct mailbox_header_lookup_ctx *headers)
{
	struct index_mail_data *data = &mail->data;
	const uint8_t *match;
	unsigned int i, field_idx, match_count;

	mail->header_seq = data->seq;
	if (mail->header_data == NULL) {
		mail->header_data = buffer_create_dynamic(default_pool, 4096);
		i_array_init(&mail->header_lines, 32);
		i_array_init(&mail->header_match, 32);
		i_array_init(&mail->header_match_lines, 32);
		mail->header_match_value = HEADER_MATCH_SKIP_COUNT;
	} else {
		buffer_set_used_size(mail->header_data, 0);
		array_clear(&mail->header_lines);
		array_clear(&mail->header_match_lines);

		mail->header_match_value += HEADER_MATCH_SKIP_COUNT;
		i_assert((mail->header_match_value &
			  (HEADER_MATCH_SKIP_COUNT-1)) == 0);
		if (mail->header_match_value == 0) {
			/* wrapped, we'll have to clear the buffer */
			array_clear(&mail->header_match);
			mail->header_match_value = HEADER_MATCH_SKIP_COUNT;
		}
	}

	if (headers != NULL) {
		for (i = 0; i < headers->count; i++) {
			array_idx_set(&mail->header_match, headers->idx[i],
				      &mail->header_match_value);
		}
	}

	if (data->wanted_headers != NULL && data->wanted_headers != headers) {
		headers = data->wanted_headers;
		for (i = 0; i < headers->count; i++) {
			array_idx_set(&mail->header_match, headers->idx[i],
				      &mail->header_match_value);
		}
	}

	/* register also all the other headers that exist in cache file */
	T_BEGIN {
		index_mail_parse_header_register_all_wanted(mail);
	} T_END;

	/* if we want sent date, it doesn't mean that we also want to cache
	   Date: header. if we have Date field's index set at this point we
	   know that we want it. otherwise add it and remember that we don't
	   want it cached. */
	field_idx = get_header_field_idx(mail->mail.mail.box, "Date",
					 MAIL_CACHE_DECISION_NO);
	match = array_get(&mail->header_match, &match_count);
	if (field_idx < match_count &&
	    match[field_idx] == mail->header_match_value) {
		/* cache Date: header */
	} else if ((data->cache_fetch_fields & MAIL_FETCH_DATE) != 0 ||
		   data->save_sent_date) {
		/* parse Date: header, but don't cache it. */
		data->dont_cache_field_idx = field_idx;
		array_idx_set(&mail->header_match, field_idx,
			      &mail->header_match_value);
	}
}