static bool
keyword_lookup(struct mail_index_sync_map_ctx *ctx,
	       const char *keyword_name, unsigned int *idx_r)
{
	struct mail_index_map *map = ctx->view->map;
	const unsigned int *idx_map;
	unsigned int i, count, keyword_idx;

	if (array_is_created(&map->keyword_idx_map) &&
	    mail_index_keyword_lookup(ctx->view->index, keyword_name,
				      &keyword_idx)) {
		/* FIXME: slow. maybe create index -> file mapping as well */
		idx_map = array_get(&map->keyword_idx_map, &count);
		for (i = 0; i < count; i++) {
			if (idx_map[i] == keyword_idx) {
				*idx_r = i;
				return TRUE;
			}
		}
	}
	return FALSE;
}
示例#2
0
static bool parse_x_keywords_real(struct mbox_sync_mail_context *ctx,
				  struct message_header_line *hdr)
{
	struct mailbox *box = &ctx->sync_ctx->mbox->box;
	ARRAY_TYPE(keyword_indexes) keyword_list;
	const unsigned int *list;
	string_t *keyword;
	size_t keyword_start;
	unsigned int i, idx, count;
	size_t pos;

	if (array_is_created(&ctx->mail.keywords))
		return FALSE; /* duplicate header, delete */

	/* read keyword indexes to temporary array first */
	keyword = t_str_new(128);
	t_array_init(&keyword_list, 16);

	for (pos = 0; pos < hdr->full_value_len; ) {
		if (IS_LWSP_LF(hdr->full_value[pos])) {
                        pos++;
			continue;
		}

		/* read the keyword string */
		keyword_start = pos;
		for (; pos < hdr->full_value_len; pos++) {
			if (IS_LWSP_LF(hdr->full_value[pos]))
				break;
		}

		str_truncate(keyword, 0);
		str_append_n(keyword, hdr->full_value + keyword_start,
			     pos - keyword_start);
		if (!mail_index_keyword_lookup(box->index, str_c(keyword),
					       &idx)) {
			/* keyword wasn't found. that means the sent mail
			   originally contained X-Keywords header. Delete it. */
			return FALSE;
		}

		/* check that the keyword isn't already added there.
		   we don't want duplicates. */
		list = array_get(&keyword_list, &count);
		for (i = 0; i < count; i++) {
			if (list[i] == idx)
				break;
		}

		if (i == count)
			array_append(&keyword_list, &idx, 1);
	}

	/* once we know how many keywords there are, we can allocate the array
	   from mail_keyword_pool without wasting memory. */
	if (array_count(&keyword_list) > 0) {
		p_array_init(&ctx->mail.keywords,
			     ctx->sync_ctx->mail_keyword_pool,
			     array_count(&keyword_list));
		array_append_array(&ctx->mail.keywords, &keyword_list);
	}

	ctx->hdr_pos[MBOX_HDR_X_KEYWORDS] = str_len(ctx->header);
	parse_trailing_whitespace(ctx, hdr);
	return TRUE;
}
示例#3
0
int mail_index_map_parse_keywords(struct mail_index_map *map)
{
	struct mail_index *index = map->index;
	const struct mail_index_ext *ext;
	const struct mail_index_keyword_header *kw_hdr;
	const struct mail_index_keyword_header_rec *kw_rec;
	const char *name;
	unsigned int i, name_area_end_offset, old_count;
	uint32_t idx;

	if (!mail_index_map_lookup_ext(map, MAIL_INDEX_EXT_KEYWORDS, &idx)) {
		if (array_is_created(&map->keyword_idx_map))
			array_clear(&map->keyword_idx_map);
		return 0;
	}
	ext = array_idx(&map->extensions, idx);

	/* Extension header contains:
	   - struct mail_index_keyword_header
	   - struct mail_index_keyword_header_rec * keywords_count
	   - const char names[] * keywords_count
	*/
	i_assert(ext->hdr_offset < map->hdr.header_size);
	kw_hdr = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
	kw_rec = (const void *)(kw_hdr + 1);
	name = (const char *)(kw_rec + kw_hdr->keywords_count);

	old_count = !array_is_created(&map->keyword_idx_map) ? 0 :
		array_count(&map->keyword_idx_map);

	/* Keywords can only be added into same mapping. Removing requires a
	   new mapping (recreating the index file) */
	if (kw_hdr->keywords_count == old_count) {
		/* nothing changed */
		return 0;
	}

	/* make sure the header is valid */
	if (kw_hdr->keywords_count < old_count) {
		mail_index_set_error(index, "Corrupted index file %s: "
				     "Keywords removed unexpectedly",
				     index->filepath);
		return -1;
	}

	if ((size_t)(name - (const char *)kw_hdr) > ext->hdr_size) {
		mail_index_set_error(index, "Corrupted index file %s: "
				     "keywords_count larger than header size",
				     index->filepath);
		return -1;
	}

	name_area_end_offset = (const char *)kw_hdr + ext->hdr_size - name;
	for (i = 0; i < kw_hdr->keywords_count; i++) {
		if (kw_rec[i].name_offset > name_area_end_offset) {
			mail_index_set_error(index, "Corrupted index file %s: "
				"name_offset points outside allocated header",
				index->filepath);
			return -1;
		}
	}
	if (name[name_area_end_offset-1] != '\0') {
		mail_index_set_error(index, "Corrupted index file %s: "
				     "Keyword header doesn't end with NUL",
				     index->filepath);
		return -1;
	}

	/* create file -> index mapping */
	if (!array_is_created(&map->keyword_idx_map)) 
		i_array_init(&map->keyword_idx_map, kw_hdr->keywords_count);

#ifdef DEBUG
	/* Check that existing headers are still the same. It's behind DEBUG
	   since it's pretty useless waste of CPU normally. */
	for (i = 0; i < array_count(&map->keyword_idx_map); i++) {
		const char *keyword = name + kw_rec[i].name_offset;
		const unsigned int *old_idx;
		unsigned int kw_idx;

		old_idx = array_idx(&map->keyword_idx_map, i);
		if (!mail_index_keyword_lookup(index, keyword, &kw_idx) ||
		    kw_idx != *old_idx) {
			mail_index_set_error(index, "Corrupted index file %s: "
					     "Keywords changed unexpectedly",
					     index->filepath);
			return -1;
		}
	}
#endif
	/* Register the newly seen keywords */
	i = array_count(&map->keyword_idx_map);
	for (; i < kw_hdr->keywords_count; i++) {
		const char *keyword = name + kw_rec[i].name_offset;
		unsigned int kw_idx;

		if (*keyword == '\0') {
			mail_index_set_error(index, "Corrupted index file %s: "
				"Empty keyword name in header",
				index->filepath);
			return -1;
		}
		mail_index_keyword_lookup_or_create(index, keyword, &kw_idx);
		array_append(&map->keyword_idx_map, &kw_idx, 1);
	}
	return 0;
}