dovecot-2.2: lib-imap-storage: imap-msgpart rewrite and API change.
dovecot at dovecot.org
dovecot at dovecot.org
Thu Jun 21 21:54:03 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/6fb61872b30a
changeset: 14622:6fb61872b30a
user: Timo Sirainen <tss at iki.fi>
date: Thu Jun 21 21:50:35 2012 +0300
description:
lib-imap-storage: imap-msgpart rewrite and API change.
The new API allows first parsing the validity of section strings and later
relying on them being valid without having to re-parse it. The
implementation also fixes a few things and adds "partial fetch cache".
diffstat:
src/lib-imap-storage/Makefile.am | 1 +
src/lib-imap-storage/imap-msgpart-url.c | 53 +-
src/lib-imap-storage/imap-msgpart.c | 707 ++++++++++++++++++++-----------
src/lib-imap-storage/imap-msgpart.h | 46 +-
src/lib-storage/mail-storage-private.h | 7 +
5 files changed, 531 insertions(+), 283 deletions(-)
diffs (truncated from 1003 to 300 lines):
diff -r bf8a885c2077 -r 6fb61872b30a src/lib-imap-storage/Makefile.am
--- a/src/lib-imap-storage/Makefile.am Thu Jun 21 21:47:06 2012 +0300
+++ b/src/lib-imap-storage/Makefile.am Thu Jun 21 21:50:35 2012 +0300
@@ -5,6 +5,7 @@
-I$(top_srcdir)/src/lib-test \
-I$(top_srcdir)/src/lib-charset \
-I$(top_srcdir)/src/lib-mail \
+ -I$(top_srcdir)/src/lib-index \
-I$(top_srcdir)/src/lib-storage \
-I$(top_srcdir)/src/lib-imap
diff -r bf8a885c2077 -r 6fb61872b30a src/lib-imap-storage/imap-msgpart-url.c
--- a/src/lib-imap-storage/imap-msgpart-url.c Thu Jun 21 21:47:06 2012 +0300
+++ b/src/lib-imap-storage/imap-msgpart-url.c Thu Jun 21 21:50:35 2012 +0300
@@ -1,3 +1,5 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
#include "lib.h"
#include "network.h"
#include "istream.h"
@@ -162,13 +164,32 @@
return 1;
}
+static int
+imap_msgpart_url_open_part(struct imap_msgpart_url *mpurl, struct mail **mail_r,
+ struct imap_msgpart **msgpart_r, const char **error_r)
+{
+ int ret;
+
+ if ((ret = imap_msgpart_url_open_mail(mpurl, mail_r, error_r)) <= 0)
+ return ret;
+
+ if (imap_msgpart_parse((*mail_r)->box, mpurl->section, msgpart_r) < 0) {
+ *error_r = "Invalid section";
+ return 0;
+ }
+ imap_msgpart_set_partial(*msgpart_r, mpurl->partial_offset,
+ mpurl->partial_size == 0 ? (uoff_t)-1 :
+ mpurl->partial_size);
+ return 1;
+}
+
int imap_msgpart_url_read_part(struct imap_msgpart_url *mpurl,
struct istream **stream_r, uoff_t *size_r,
const char **error_r)
{
struct mail *mail;
- struct istream *input;
- uoff_t part_size;
+ struct imap_msgpart *msgpart;
+ struct imap_msgpart_open_result result;
int ret;
if (mpurl->input != NULL) {
@@ -179,20 +200,20 @@
}
/* open mail if it is not yet open */
- if ((ret = imap_msgpart_url_open_mail(mpurl, &mail, error_r)) <= 0)
+ ret = imap_msgpart_url_open_part(mpurl, &mail, &msgpart, error_r);
+ if (ret <= 0)
return ret;
/* open the referenced part as a stream */
- if ((ret = imap_msgpart_open(mail, mpurl->section,
- mpurl->partial_offset, mpurl->partial_size,
- &input, &part_size, error_r)) <= 0)
+ ret = imap_msgpart_open(mail, msgpart, &result);
+ imap_msgpart_free(&msgpart);
+ if (ret < 0) {
+ *error_r = mailbox_get_last_error(mail->box, NULL);
return ret;
+ }
- mpurl->input = input;
- mpurl->part_size = part_size;
-
- *stream_r = input;
- *size_r = part_size;
+ *stream_r = mpurl->input = result.input;
+ *size_r = mpurl->part_size = result.size;
return 1;
}
@@ -200,17 +221,17 @@
const char **error_r)
{
struct mail *mail;
+ struct imap_msgpart *msgpart;
int ret;
if (mpurl->input != NULL)
return 1;
/* open mail if it is not yet open */
- if ((ret = imap_msgpart_url_open_mail(mpurl, &mail, error_r)) <= 0)
- return ret;
-
- /* open the referenced part as a stream */
- return imap_msgpart_verify(mail, mpurl->section, error_r);
+ ret = imap_msgpart_url_open_part(mpurl, &mail, &msgpart, error_r);
+ if (ret > 0)
+ imap_msgpart_free(&msgpart);
+ return ret;
}
void imap_msgpart_url_free(struct imap_msgpart_url **_mpurl)
diff -r bf8a885c2077 -r 6fb61872b30a src/lib-imap-storage/imap-msgpart.c
--- a/src/lib-imap-storage/imap-msgpart.c Thu Jun 21 21:47:06 2012 +0300
+++ b/src/lib-imap-storage/imap-msgpart.c Thu Jun 21 21:50:35 2012 +0300
@@ -1,25 +1,89 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
#include "lib.h"
#include "array.h"
#include "istream.h"
#include "istream-crlf.h"
+#include "istream-nonuls.h"
#include "istream-header-filter.h"
#include "message-parser.h"
-#include "mail-storage.h"
+#include "mail-storage-private.h"
#include "mail-namespace.h"
#include "imap-parser.h"
#include "imap-msgpart.h"
-int imap_msgpart_find(struct mail *mail, const char *section,
- const struct message_part **part_r,
- const char **subsection_r)
+enum fetch_type {
+ FETCH_FULL,
+ FETCH_MIME,
+ FETCH_HEADER,
+ FETCH_HEADER_FIELDS,
+ FETCH_HEADER_FIELDS_NOT,
+ FETCH_BODY
+};
+
+struct imap_msgpart {
+ pool_t pool;
+
+ /* "" for root, otherwise e.g. "1.2.3". the .MIME, .HEADER, etc.
+ suffix not included */
+ const char *section_number;
+ enum fetch_type fetch_type;
+ enum mail_fetch_field wanted_fields;
+
+ /* HEADER.FIELDS[.NOT] (list of headers) */
+ struct mailbox_header_lookup_ctx *header_ctx;
+ const char *const *headers;
+
+ /* which part of the message part to fetch (default: 0..(uoff_t)-1) */
+ uoff_t partial_offset, partial_size;
+};
+
+struct imap_msgpart_open_ctx {
+ /* from matching message_part, set after opening: */
+ uoff_t physical_pos;
+ struct message_size mime_hdr_size;
+ struct message_size mime_body_size;
+};
+
+static struct imap_msgpart *imap_msgpart_type(enum fetch_type fetch_type)
{
- struct message_part *part;
+ struct imap_msgpart *msgpart;
+ pool_t pool;
+
+ pool = pool_alloconly_create("imap msgpart", sizeof(*msgpart)+32);
+ msgpart = p_new(pool, struct imap_msgpart, 1);
+ msgpart->pool = pool;
+ msgpart->partial_size = (uoff_t)-1;
+ msgpart->fetch_type = fetch_type;
+ if (fetch_type == FETCH_HEADER || fetch_type == FETCH_FULL)
+ msgpart->wanted_fields |= MAIL_FETCH_STREAM_HEADER;
+ if (fetch_type == FETCH_BODY || fetch_type == FETCH_FULL)
+ msgpart->wanted_fields |= MAIL_FETCH_STREAM_BODY;
+ return msgpart;
+}
+
+struct imap_msgpart *imap_msgpart_full(void)
+{
+ return imap_msgpart_type(FETCH_FULL);
+}
+
+struct imap_msgpart *imap_msgpart_header(void)
+{
+ return imap_msgpart_type(FETCH_HEADER);
+}
+
+struct imap_msgpart *imap_msgpart_body(void)
+{
+ return imap_msgpart_type(FETCH_BODY);
+}
+
+static struct message_part *
+imap_msgpart_find(struct message_part *parts, const char *section)
+{
+ struct message_part *part = parts;
const char *path;
unsigned int num;
- if (mail_get_parts(mail, &part) < 0)
- return -1;
-
path = section;
while (*path >= '0' && *path <= '9' && part != NULL) {
/* get part number, we have already verified its validity */
@@ -53,21 +117,18 @@
part = part->children;
}
}
-
- *part_r = part;
- *subsection_r = path;
- return 0;
+ i_assert(part == NULL || *path == '\0');
+ return part;
}
static int
-imap_msgpart_get_header_fields(const char *header_list,
- const char *const **fields_r, size_t *count_r)
+imap_msgpart_get_header_fields(pool_t pool, const char *header_list,
+ ARRAY_TYPE(const_string) *fields)
{
struct istream *input;
struct imap_parser *parser;
const struct imap_arg *args, *hdr_list;
unsigned int list_count;
- ARRAY_TYPE(const_string) fields = ARRAY_INIT;
unsigned int i;
int result = 0;
@@ -76,304 +137,452 @@
if (imap_parser_finish_line(parser, 0, 0, &args) > 0 &&
imap_arg_get_list_full(args, &hdr_list, &list_count) &&
+ args[1].type == IMAP_ARG_EOL &&
list_count > 0) {
const char *value;
- if (fields_r != NULL)
- t_array_init(&fields, list_count);
-
+ p_array_init(fields, pool, list_count);
for (i = 0; i < list_count; i++) {
if (!imap_arg_get_astring(&hdr_list[i], &value)) {
result = -1;
break;
}
- if (fields_r != NULL) {
- value = t_str_ucase(value);
- array_append(&fields, &value, 1);
- }
- }
-
- if (fields_r != NULL) {
- *fields_r = array_get(&fields, &list_count);
- *count_r = list_count;
+ value = p_strdup(pool, t_str_ucase(value));
+ array_append(fields, &value, 1);
}
} else {
result = -1;
}
+ /* istream-header-filter requires headers to be sorted */
+ array_sort(fields, i_strcasecmp_p);
+
imap_parser_unref(&parser);
i_stream_unref(&input);
return result;
}
static int
-imap_msgpart_verify_header_fields(const char *header_list, const char **error_r)
+imap_msgpart_parse_header_fields(struct mailbox *box,
+ struct imap_msgpart *msgpart,
+ const char *header_list)
{
+ ARRAY_TYPE(const_string) fields;
+
/* HEADER.FIELDS (list), HEADER.FIELDS.NOT (list) */
- if (imap_msgpart_get_header_fields(header_list, NULL, NULL) < 0) {
- *error_r = "Invalid header fields";
+ if (imap_msgpart_get_header_fields(msgpart->pool, header_list,
+ &fields) < 0)
+ return -1;
+
+ (void)array_append_space(&fields);
+ msgpart->headers = array_idx(&fields, 0);
+ msgpart->header_ctx = mailbox_header_lookup_init(box, msgpart->headers);
+ return 0;
+}
+
+int imap_msgpart_parse(struct mailbox *box, const char *section,
+ struct imap_msgpart **msgpart_r)
More information about the dovecot-cvs
mailing list