[dovecot-cvs] dovecot/src/lib-storage/index index-mail-headers.c, 1.43, 1.44 index-mail.c, 1.73, 1.74 index-mail.h, 1.30, 1.31 index-search.c, 1.100, 1.101

cras at dovecot.org cras at dovecot.org
Tue Mar 29 19:48:48 EEST 2005


Update of /var/lib/cvs/dovecot/src/lib-storage/index
In directory talvi:/tmp/cvs-serv27861/lib-storage/index

Modified Files:
	index-mail-headers.c index-mail.c index-mail.h index-search.c 
Log Message:
Renamed mail_get_header() to mail_get_first_header() and mail_gets_headers()
to mail_get_header_stream(). Added new mail_get_headers() which returns
NULL-terminated string list of all found headers.



Index: index-mail-headers.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/index-mail-headers.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- index-mail-headers.c	29 Mar 2005 15:56:19 -0000	1.43
+++ index-mail-headers.c	29 Mar 2005 16:48:45 -0000	1.44
@@ -35,7 +35,6 @@
 
 static void index_mail_parse_header_finish(struct index_mail *mail)
 {
-	static uint32_t null = 0;
 	struct index_mail_line *lines;
 	const unsigned char *header, *data;
 	const uint8_t *match;
@@ -56,21 +55,35 @@
 	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 match[] doesn't have header_match_value,
+			   it belongs to some older header parsing and we
+			   just want to ignore it. */
+			i_assert(match[match_idx] !=
+				 mail->header_match_value + 1);
 			if (match[match_idx] == mail->header_match_value) {
 				/* this header doesn't exist. remember that. */
-				array_idx_set(&mail->header_offsets,
-					      match_idx, &null);
 				mail_cache_add(mail->trans->cache_trans,
 					       mail->data.seq, match_idx,
 					       NULL, 0);
 			}
 			match_idx++;
 		}
-		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++;
+		}
+
+		/* 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));
@@ -85,7 +98,7 @@
 			buffer_append(buf, &lines[j].line_num,
 				      sizeof(lines[j].line_num));
 		}
-		buffer_append(buf, &null, sizeof(uint32_t));
+		buffer_append_zero(buf, sizeof(uint32_t));
 
 		if (noncontiguous) {
 			for (; i < j; i++) {
@@ -128,19 +141,18 @@
 		ARRAY_CREATE(&mail->header_lines, default_pool,
 			     struct index_mail_line, 32);
 		ARRAY_CREATE(&mail->header_match, default_pool, uint8_t, 32);
-		ARRAY_CREATE(&mail->header_offsets, default_pool,
-			     uint32_t, 32);
+		ARRAY_CREATE(&mail->header_match_lines, default_pool,
+			     unsigned int, 32);
 	} else {
 		buffer_set_used_size(mail->header_data, 0);
 		array_clear(&mail->header_lines);
-		array_clear(&mail->header_offsets);
+		array_clear(&mail->header_match_lines);
 	}
 
         mail->header_match_value += 2;
 	if (mail->header_match_value == 0) {
 		/* @UNSAFE: wrapped, we'll have to clear the buffer */
-		memset(array_modifyable_idx(&mail->header_match, 0), 0,
-		       array_count(&mail->header_match));
+		array_clear(&mail->header_match);
 		mail->header_match_value = 2;
 	}
 
@@ -181,7 +193,7 @@
 	const char *cache_field_name;
 	unsigned int field_idx, count;
 	uint8_t *match;
-	int timezone, first_hdr = FALSE;
+	int timezone;
 
         data->parse_line_num++;
 
@@ -265,7 +277,6 @@
 	match = array_get_modifyable(&mail->header_match, &count);
 	if (field_idx < count && match[field_idx] == mail->header_match_value) {
 		/* first header */
-		first_hdr = TRUE;
 		match[field_idx]++;
 	} else if (!data->parse_line.cache &&
 		   (field_idx >= count ||
@@ -279,12 +290,6 @@
 		data->parse_line.line_num = data->parse_line_num;
 		str_append(mail->header_data, hdr->name);
 		str_append_n(mail->header_data, hdr->middle, hdr->middle_len);
-
-		if (first_hdr) {
-			/* save the offset to first header */
-			uint32_t pos = str_len(mail->header_data);
-			array_idx_set(&mail->header_offsets, field_idx, &pos);
-		}
 	}
 	str_append_n(mail->header_data, hdr->value, hdr->value_len);
 	if (!hdr->no_newline)
@@ -354,7 +359,7 @@
 	mail->data.save_envelope = TRUE;
 	header_ctx = mailbox_header_lookup_init(&mail->ibox->box,
 						imap_envelope_headers);
-	stream = mail_get_headers(&mail->mail.mail, header_ctx);
+	stream = mail_get_header_stream(&mail->mail.mail, header_ctx);
 	if (mail->data.envelope == NULL && stream != NULL) {
 		/* we got the headers from cache - parse them to get the
 		   envelope */
@@ -422,32 +427,49 @@
 	return -1;
 }
 
-static const char *
+static const char *const *
 index_mail_get_parsed_header(struct index_mail *mail, unsigned int field_idx)
 {
-	const unsigned char *data;
-	const uint32_t *offsets;
-	unsigned int count;
-	size_t size;
+	array_t ARRAY_DEFINE(header_values, const char *);
+        const struct index_mail_line *lines;
+	const unsigned char *header;
+	const unsigned int *line_idx;
+	const char *value;
+	unsigned int i, lines_count, first_line_idx;
 
-	offsets = array_get(&mail->header_offsets, &count);
-	i_assert(field_idx <= count && offsets[field_idx] != 0);
+	line_idx = array_idx(&mail->header_match_lines, field_idx);
+	i_assert(*line_idx != 0);
+	first_line_idx = *line_idx - 1;
 
-	data = buffer_get_data(mail->header_data, &size);
-        size = get_header_size(mail->header_data, offsets[field_idx]);
-	return p_strndup(mail->data_pool, data + offsets[field_idx], size);
+	ARRAY_CREATE(&header_values, mail->data_pool, const char *, 4);
+	header = buffer_get_data(mail->header_data, NULL);
+
+	lines = array_get(&mail->header_lines, &lines_count);
+	for (i = first_line_idx; i < lines_count; i++) {
+		if (lines[i].field_idx != lines[first_line_idx].field_idx)
+			break;
+
+		value = p_strndup(mail->data_pool, header + lines[i].start_pos,
+				  lines[i].end_pos - lines[i].start_pos);
+		array_append(&header_values, &value, 1);
+	}
+
+	value = NULL;
+	array_append(&header_values, &value, sizeof(value));
+	return array_idx(&header_values, 0);
 }
 
-const char *index_mail_get_header(struct mail *_mail, const char *field)
+const char *const *index_mail_get_headers(struct mail *_mail, const char *field)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
-	const char *headers[2];
+	const char *headers[2], *value;
 	struct mailbox_header_lookup_ctx *headers_ctx;
-	const unsigned char *data;
+	unsigned char *data;
 	unsigned int field_idx;
 	string_t *dest;
 	size_t i, len;
 	int ret;
+	array_t ARRAY_DEFINE(header_values, const char *);
 
 	field_idx = get_header_field_idx(mail->ibox, field);
 
@@ -479,26 +501,40 @@
 		return ret == 0 ? NULL :
 			index_mail_get_parsed_header(mail, field_idx);
 	}
+	data = buffer_get_modifyable_data(dest, &len);
 
-	if (str_len(dest) == 0) {
+	if (len == 0) {
 		/* cached as non-existing. */
-		return NULL;
+		return p_new(mail->data_pool, const char *, 1);
 	}
 
-	/* cached. skip "header name: " in dest. */
-	data = str_data(dest);
-	len = str_len(dest);
+	ARRAY_CREATE(&header_values, mail->data_pool, const char *, 4);
+
+	/* cached. skip "header name: " parts in dest. */
 	for (i = 0; i < len; i++) {
 		if (data[i] == ':') {
 			if (i+1 != len && data[++i] == ' ') i++;
-			break;
+
+			/* @UNSAFE */
+			len = get_header_size(dest, i);
+			data[i + len] = '\0';
+			value = (const char *)data + i;
+			i += len + 1;
+
+			array_append(&header_values, &value, sizeof(value));
 		}
 	}
 
-	/* return only the first field in case there's multiple. */
-        len = get_header_size(dest, i);
-	buffer_set_used_size(dest, i + len);
-	return str_c(dest) + i;
+	value = NULL;
+	array_append(&header_values, &value, sizeof(value));
+	return array_idx(&header_values, 0);
+}
+
+const char *index_mail_get_first_header(struct mail *mail, const char *field)
+{
+	const char *const *list = index_mail_get_headers(mail, field);
+
+	return list == NULL ? NULL : list[0];
 }
 
 static void header_cache_callback(struct message_header_line *hdr,
@@ -513,8 +549,8 @@
 }
 
 struct istream *
-index_mail_get_headers(struct mail *_mail,
-		       struct mailbox_header_lookup_ctx *_headers)
+index_mail_get_header_stream(struct mail *_mail,
+			     struct mailbox_header_lookup_ctx *_headers)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_header_lookup_ctx *headers =

Index: index-mail.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/index-mail.c,v
retrieving revision 1.73
retrieving revision 1.74
diff -u -d -r1.73 -r1.74
--- index-mail.c	29 Mar 2005 15:56:19 -0000	1.73
+++ index-mail.c	29 Mar 2005 16:48:45 -0000	1.74
@@ -240,7 +240,7 @@
 
 	if (data->sent_date.time == (time_t)-1) {
 		data->save_sent_date = TRUE;
-		str = mail_get_header(_mail, "Date");
+		str = mail_get_first_header(_mail, "Date");
 		if (data->sent_date.time == (time_t)-1) {
 			if (!message_date_parse((const unsigned char *)str,
 						(size_t)-1,
@@ -763,8 +763,8 @@
 		array_free(&mail->header_lines);
 	if (array_is_created(&mail->header_match))
 		array_free(&mail->header_match);
-	if (array_is_created(&mail->header_offsets))
-		array_free(&mail->header_offsets);
+	if (array_is_created(&mail->header_match_lines))
+		array_free(&mail->header_match_lines);
 
 	pool_unref(mail->data_pool);
 	pool_unref(mail->mail.pool);

Index: index-mail.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/index-mail.h,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- index-mail.h	29 Mar 2005 15:56:19 -0000	1.30
+++ index-mail.h	29 Mar 2005 16:48:45 -0000	1.31
@@ -103,7 +103,7 @@
 	string_t *header_data;
 	array_t ARRAY_DEFINE(header_lines, struct index_mail_line);
 	array_t ARRAY_DEFINE(header_match, uint8_t);
-	array_t ARRAY_DEFINE(header_offsets, uint32_t);
+	array_t ARRAY_DEFINE(header_match_lines, unsigned int);
 	uint8_t header_match_value;
 };
 
@@ -123,10 +123,12 @@
 			     struct mailbox_header_lookup_ctx *headers);
 void index_mail_headers_get_envelope(struct index_mail *mail);
 
-const char *index_mail_get_header(struct mail *_mail, const char *field);
+const char *index_mail_get_first_header(struct mail *_mail, const char *field);
+const char *const *
+index_mail_get_headers(struct mail *_mail, const char *field);
 struct istream *
-index_mail_get_headers(struct mail *_mail,
-		       struct mailbox_header_lookup_ctx *headers);
+index_mail_get_header_stream(struct mail *_mail,
+			     struct mailbox_header_lookup_ctx *headers);
 
 enum mail_flags index_mail_get_flags(struct mail *_mail);
 const char *const *index_mail_get_keywords(struct mail *_mail);

Index: index-search.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/index/index-search.c,v
retrieving revision 1.100
retrieving revision 1.101
diff -u -d -r1.100 -r1.101
--- index-search.c	15 Mar 2005 19:01:52 -0000	1.100
+++ index-search.c	29 Mar 2005 16:48:46 -0000	1.101
@@ -486,7 +486,7 @@
 			headers_ctx =
 				mailbox_header_lookup_init(&ctx->ibox->box,
 							   headers);
-			input = mail_get_headers(ctx->mail, headers_ctx);
+			input = mail_get_header_stream(ctx->mail, headers_ctx);
 			if (input == NULL) {
 				mailbox_header_lookup_deinit(headers_ctx);
 				return FALSE;



More information about the dovecot-cvs mailing list