Mercurial > dovecot > core-2.2
changeset 3248:ff47e78ad717 HEAD
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.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 29 Mar 2005 19:48:42 +0300 |
parents | e7166e2f8b9b |
children | c913cf1dfb08 |
files | src/imap/imap-sort.c src/imap/imap-thread.c src/lib-storage/index/index-mail-headers.c src/lib-storage/index/index-mail.c src/lib-storage/index/index-mail.h src/lib-storage/index/index-search.c src/lib-storage/index/maildir/maildir-mail.c src/lib-storage/index/mbox/mbox-mail.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.h src/lib-storage/mail.c |
diffstat | 11 files changed, 124 insertions(+), 76 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/imap-sort.c Tue Mar 29 18:56:19 2005 +0300 +++ b/src/imap/imap-sort.c Tue Mar 29 19:48:42 2005 +0300 @@ -290,7 +290,7 @@ struct message_address *addr; const char *str; - str = mail_get_header(mail, field); + str = mail_get_first_header(mail, field); if (str == NULL) return NULL; @@ -356,7 +356,7 @@ } if (ctx->common_mask & MAIL_SORT_SUBJECT) { - str = mail_get_header(mail, "subject"); + str = mail_get_first_header(mail, "subject"); if (str != NULL) { str = imap_get_base_subject_cased( pool_datastack_create(), str, NULL); @@ -475,7 +475,7 @@ if (ctx->common_mask & MAIL_SORT_SUBJECT) str = ctx->last_subject; else { - str = mail_get_header(mail, "subject"); + str = mail_get_first_header(mail, "subject"); if (str != NULL) { str = imap_get_base_subject_cased( @@ -580,7 +580,7 @@ switch (type) { case MAIL_SORT_SUBJECT: - str = mail_get_header(mail, "subject"); + str = mail_get_first_header(mail, "subject"); if (str == NULL) return NULL;
--- a/src/imap/imap-thread.c Tue Mar 29 18:56:19 2005 +0300 +++ b/src/imap/imap-thread.c Tue Mar 29 19:48:42 2005 +0300 @@ -448,14 +448,14 @@ if (sent_date == (time_t)-1) sent_date = 0; - message_id = mail_get_header(mail, "message-id"); + message_id = mail_get_first_header(mail, "message-id"); node = update_message(ctx, get_msgid(&message_id), sent_date, ctx->id_is_uid ? mail->uid : mail->seq); /* link references */ - references = mail_get_header(mail, "references"); + references = mail_get_first_header(mail, "references"); if (!link_references(ctx, node, references)) { - in_reply_to = mail_get_header(mail, "in-reply-to"); + in_reply_to = mail_get_first_header(mail, "in-reply-to"); refid = in_reply_to == NULL ? NULL : get_msgid(&in_reply_to); if (refid != NULL) @@ -693,7 +693,7 @@ if (seq != 0 && mail_set_seq(ctx->mail, seq) == 0) { t_push(); - subject = mail_get_header(ctx->mail, "subject"); + subject = mail_get_first_header(ctx->mail, "subject"); add_base_subject(ctx, subject, node); t_pop(); }
--- a/src/lib-storage/index/index-mail-headers.c Tue Mar 29 18:56:19 2005 +0300 +++ b/src/lib-storage/index/index-mail-headers.c Tue Mar 29 19:48:42 2005 +0300 @@ -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; + + line_idx = array_idx(&mail->header_match_lines, field_idx); + i_assert(*line_idx != 0); + first_line_idx = *line_idx - 1; + + ARRAY_CREATE(&header_values, mail->data_pool, const char *, 4); + header = buffer_get_data(mail->header_data, NULL); - offsets = array_get(&mail->header_offsets, &count); - i_assert(field_idx <= count && offsets[field_idx] != 0); + 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; - 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); + 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 =
--- a/src/lib-storage/index/index-mail.c Tue Mar 29 18:56:19 2005 +0300 +++ b/src/lib-storage/index/index-mail.c Tue Mar 29 19:48:42 2005 +0300 @@ -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);
--- a/src/lib-storage/index/index-mail.h Tue Mar 29 18:56:19 2005 +0300 +++ b/src/lib-storage/index/index-mail.h Tue Mar 29 19:48:42 2005 +0300 @@ -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);
--- a/src/lib-storage/index/index-search.c Tue Mar 29 18:56:19 2005 +0300 +++ b/src/lib-storage/index/index-search.c Tue Mar 29 19:48:42 2005 +0300 @@ -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;
--- a/src/lib-storage/index/maildir/maildir-mail.c Tue Mar 29 18:56:19 2005 +0300 +++ b/src/lib-storage/index/maildir/maildir-mail.c Tue Mar 29 19:48:42 2005 +0300 @@ -239,8 +239,9 @@ index_mail_get_date, maildir_mail_get_virtual_size, maildir_mail_get_physical_size, - index_mail_get_header, + index_mail_get_first_header, index_mail_get_headers, + index_mail_get_header_stream, maildir_mail_get_stream, maildir_mail_get_special, index_mail_update_flags,
--- a/src/lib-storage/index/mbox/mbox-mail.c Tue Mar 29 18:56:19 2005 +0300 +++ b/src/lib-storage/index/mbox/mbox-mail.c Tue Mar 29 19:48:42 2005 +0300 @@ -174,8 +174,9 @@ index_mail_get_date, index_mail_get_virtual_size, mbox_mail_get_physical_size, - index_mail_get_header, + index_mail_get_first_header, index_mail_get_headers, + index_mail_get_header_stream, mbox_mail_get_stream, mbox_mail_get_special, index_mail_update_flags,
--- a/src/lib-storage/mail-storage-private.h Tue Mar 29 18:56:19 2005 +0300 +++ b/src/lib-storage/mail-storage-private.h Tue Mar 29 19:48:42 2005 +0300 @@ -165,10 +165,11 @@ uoff_t (*get_virtual_size)(struct mail *mail); uoff_t (*get_physical_size)(struct mail *mail); - const char *(*get_header)(struct mail *mail, const char *field); + const char *(*get_first_header)(struct mail *mail, const char *field); + const char *const *(*get_headers)(struct mail *mail, const char *field); struct istream * - (*get_headers)(struct mail *mail, - struct mailbox_header_lookup_ctx *headers); + (*get_header_stream)(struct mail *mail, + struct mailbox_header_lookup_ctx *headers); struct istream *(*get_stream)(struct mail *mail, struct message_size *hdr_size, struct message_size *body_size);
--- a/src/lib-storage/mail-storage.h Tue Mar 29 18:56:19 2005 +0300 +++ b/src/lib-storage/mail-storage.h Tue Mar 29 19:48:42 2005 +0300 @@ -415,10 +415,13 @@ uoff_t mail_get_physical_size(struct mail *mail); /* Get value for single header field */ -const char *mail_get_header(struct mail *mail, const char *field); +const char *mail_get_first_header(struct mail *mail, const char *field); +/* Return a NULL-terminated list of values for each found field. */ +const char *const *mail_get_headers(struct mail *mail, const char *field); /* Returns stream containing specified headers. */ -struct istream *mail_get_headers(struct mail *mail, - struct mailbox_header_lookup_ctx *headers); +struct istream * +mail_get_header_stream(struct mail *mail, + struct mailbox_header_lookup_ctx *headers); /* Returns input stream pointing to beginning of message header. hdr_size and body_size are updated unless they're NULL. */ struct istream *mail_get_stream(struct mail *mail,
--- a/src/lib-storage/mail.c Tue Mar 29 18:56:19 2005 +0300 +++ b/src/lib-storage/mail.c Tue Mar 29 19:48:42 2005 +0300 @@ -74,23 +74,27 @@ return p->v.get_physical_size(mail); } -const char *mail_get_header(struct mail *mail, const char *field) +const char *mail_get_first_header(struct mail *mail, const char *field) { + struct mail_private *p = (struct mail_private *)mail; + + return p->v.get_first_header(mail, field); +} + +const char *const *mail_get_headers(struct mail *mail, const char *field) { struct mail_private *p = (struct mail_private *)mail; - return p->v.get_header(mail, field); -} + return p->v.get_headers(mail, field); } -struct istream *mail_get_headers(struct mail *mail, - struct mailbox_header_lookup_ctx *headers) -{ +struct istream * +mail_get_header_stream(struct mail *mail, + struct mailbox_header_lookup_ctx *headers) { struct mail_private *p = (struct mail_private *)mail; - return p->v.get_headers(mail, headers); -} + return p->v.get_header_stream(mail, headers); } struct istream *mail_get_stream(struct mail *mail,