[dovecot-cvs] dovecot/src/lib-storage/index index-mail.c,1.6,1.7 index-mail.h,1.2,1.3 index-save.c,1.29,1.30 index-search.c,1.68,1.69 index-storage.h,1.34,1.35
cras at procontrol.fi
cras at procontrol.fi
Wed Mar 26 19:29:05 EET 2003
Update of /home/cvs/dovecot/src/lib-storage/index
In directory danu:/tmp/cvs-serv10853/lib-storage/index
Modified Files:
index-mail.c index-mail.h index-save.c index-search.c
index-storage.h
Log Message:
Better handling for multiline headers. Before we skipped headers larger than
input buffer size (8k with read (default), 256k with mmap). The skipping was
also a bit buggy.
Now we parse the lines one at a time. There's also a way to read the header
fully into memory before parsing it, if really needed.
Index: index-mail.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-mail.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- index-mail.c 26 Mar 2003 15:40:16 -0000 1.6
+++ index-mail.c 26 Mar 2003 17:29:02 -0000 1.7
@@ -16,55 +16,6 @@
#include <ctype.h>
-static int get_envelope_header_field(const char *name,
- enum imap_envelope_field *ret)
-{
- *ret = (enum imap_envelope_field)-1;
-
- switch (i_toupper(*name)) {
- case 'B':
- if (strcasecmp(name, "bcc") == 0)
- *ret = IMAP_ENVELOPE_BCC;
- break;
- case 'C':
- if (strcasecmp(name, "cc") == 0)
- *ret = IMAP_ENVELOPE_CC;
- break;
- case 'D':
- if (strcasecmp(name, "date") == 0)
- *ret = IMAP_ENVELOPE_DATE;
- break;
- case 'F':
- if (strcasecmp(name, "from") == 0)
- *ret = IMAP_ENVELOPE_FROM;
- break;
- case 'I':
- if (strcasecmp(name, "in-reply-to") == 0)
- *ret = IMAP_ENVELOPE_IN_REPLY_TO;
- break;
- case 'M':
- if (strcasecmp(name, "message-id") == 0)
- *ret = IMAP_ENVELOPE_MESSAGE_ID;
- break;
- case 'R':
- if (strcasecmp(name, "reply-to") == 0)
- *ret = IMAP_ENVELOPE_REPLY_TO;
- break;
- case 'S':
- if (strcasecmp(name, "subject") == 0)
- *ret = IMAP_ENVELOPE_SUBJECT;
- if (strcasecmp(name, "sender") == 0)
- *ret = IMAP_ENVELOPE_SENDER;
- break;
- case 'T':
- if (strcasecmp(name, "to") == 0)
- *ret = IMAP_ENVELOPE_TO;
- break;
- }
-
- return *ret != (enum imap_envelope_field)-1;
-}
-
static struct message_part *get_cached_parts(struct index_mail *mail)
{
struct message_part *part;
@@ -192,20 +143,17 @@
}
void index_mail_parse_header(struct message_part *part __attr_unused__,
- const unsigned char *name, size_t name_len,
- const unsigned char *value, size_t value_len,
- void *context)
+ struct message_header_line *hdr, void *context)
{
struct index_mail *mail = context;
struct index_mail_data *data = &mail->data;
- struct cached_header *hdr;
+ struct cached_header *cached_hdr;
if (data->save_envelope) {
+ imap_envelope_parse_header(mail->pool,
+ &data->envelope_data, hdr);
- imap_envelope_parse_header(mail->pool, &data->envelope_data,
- name, name_len, value, value_len);
-
- if (name_len == 0) {
+ if (hdr == NULL) {
/* finalize the envelope */
string_t *str;
@@ -215,37 +163,51 @@
}
}
- if (name_len == 4 && data->save_sent_time &&
- memcasecmp(name, "date",4) == 0) {
- if (!message_date_parse(value, value_len, &data->sent_time,
- &data->sent_timezone)) {
- /* 0 == parse error */
+ if (hdr == NULL) {
+ /* end of headers */
+ if (data->save_sent_time) {
+ /* not found */
data->sent_time = 0;
data->sent_timezone = 0;
+ data->save_sent_time = FALSE;
}
- data->save_sent_time = FALSE;
+ return;
}
- if (name_len == 0) {
- /* end of headers */
- if (data->save_sent_time) {
- /* not found */
+ if (data->save_sent_time && strcasecmp(hdr->name, "Date") == 0) {
+ if (hdr->continues) {
+ hdr->use_full_value = TRUE;
+ return;
+ }
+ if (!message_date_parse(hdr->full_value, hdr->full_value_len,
+ &data->sent_time,
+ &data->sent_timezone)) {
+ /* 0 == parse error */
data->sent_time = 0;
data->sent_timezone = 0;
- data->save_sent_time = FALSE;
}
+ data->save_sent_time = FALSE;
}
- for (hdr = data->headers; hdr != NULL; hdr = hdr->next) {
- if (hdr->name_len == name_len &&
- memcasecmp(hdr->name, name, name_len) == 0) {
+ cached_hdr = data->headers;
+ while (cached_hdr != NULL) {
+ if (cached_hdr->name_len == hdr->name_len &&
+ memcasecmp(hdr->name, hdr->name, hdr->name_len) == 0) {
/* save only the first header */
- if (hdr->value == NULL) {
- hdr->value = p_strndup(mail->pool,
- value, value_len);
+ if (cached_hdr->value != NULL)
+ break;
+
+ if (hdr->continues) {
+ hdr->use_full_value = TRUE;
+ break;
}
+
+ cached_hdr->value = p_strndup(mail->pool,
+ hdr->full_value,
+ hdr->full_value_len);
break;
}
+ cached_hdr = cached_hdr->next;
}
}
@@ -479,7 +441,7 @@
}
if (data->parse_header || data->envelope == NULL ||
- !get_envelope_header_field(field, &env_field)) {
+ !imap_envelope_get_field(field, &env_field)) {
/* if we have to parse the header, do it even if we could use
envelope - envelope parsing would just slow up. */
prepend_cached_header(mail, field);
@@ -528,7 +490,7 @@
const char *ret = NULL;
if (data->envelope != NULL &&
- get_envelope_header_field(field, &env_field)) {
+ imap_envelope_get_field(field, &env_field)) {
/* prefer parsing envelope - faster than having to actually
parse the header field */
t_push();
@@ -748,7 +710,7 @@
int envelope_headers = FALSE;
for (tmp = mail->wanted_headers; *tmp != NULL; tmp++) {
- if (get_envelope_header_field(*tmp, &env_field))
+ if (imap_envelope_get_field(*tmp, &env_field))
envelope_headers = TRUE;
else {
open_mail = TRUE;
Index: index-mail.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-mail.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- index-mail.h 21 Jan 2003 19:56:33 -0000 1.2
+++ index-mail.h 26 Mar 2003 17:29:02 -0000 1.3
@@ -38,6 +38,7 @@
pool_t pool;
struct index_mailbox *ibox;
+ buffer_t *header_buf;
enum mail_fetch_field wanted_fields;
const char *const *wanted_headers;
@@ -51,8 +52,6 @@
void index_mail_init_parse_header(struct index_mail *mail);
void index_mail_parse_header(struct message_part *part,
- const unsigned char *name, size_t name_len,
- const unsigned char *value, size_t value_len,
- void *context);
+ struct message_header_line *hdr, void *context);
#endif
Index: index-save.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-save.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- index-save.c 5 Mar 2003 01:43:16 -0000 1.29
+++ index-save.c 26 Mar 2003 17:29:02 -0000 1.30
@@ -9,19 +9,6 @@
#include <stdlib.h>
#include <unistd.h>
-struct save_header_context {
- struct mail_storage *storage;
- const char *path;
-
- struct ostream *output;
- write_func_t *write_func;
-
- header_callback_t *header_callback;
- void *context;
-
- int failed;
-};
-
static int write_with_crlf(struct ostream *output, const void *v_data,
size_t size)
{
@@ -103,45 +90,53 @@
}
}
-static void save_header_callback(struct message_part *part __attr_unused__,
- const unsigned char *name, size_t name_len,
- const unsigned char *value, size_t value_len,
- void *context)
+static int save_headers(struct istream *input, struct ostream *output,
+ header_callback_t *header_callback, void *context,
+ write_func_t *write_func)
{
- struct save_header_context *ctx = context;
- int ret;
+ struct message_header_parser_ctx *hdr_ctx;
+ struct message_header_line *hdr;
+ int ret, failed = FALSE;
- if (ctx->failed)
- return;
+ hdr_ctx = message_parse_header_init(input, NULL);
+ while ((hdr = message_parse_header_next(hdr_ctx)) != NULL) {
+ ret = header_callback(hdr->name, write_func, context);
+ if (ret <= 0) {
+ if (ret < 0) {
+ failed = TRUE;
+ break;
+ }
+ continue;
+ }
- ret = ctx->header_callback(name, name_len, ctx->write_func,
- ctx->context);
- if (ret <= 0) {
- if (ret < 0)
- ctx->failed = TRUE;
- return;
+ if (!hdr->eoh) {
+ if (!hdr->continued) {
+ (void)o_stream_send(output, hdr->name,
+ hdr->name_len);
+ (void)o_stream_send(output, ": ", 2);
+ }
+ (void)o_stream_send(output, hdr->value, hdr->value_len);
+ if (!hdr->no_newline)
+ write_func(output, "\n", 1);
+ }
}
+ if (!failed) {
+ if (header_callback(NULL, write_func, context) < 0)
+ failed = TRUE;
- if (name_len == 0) {
- name = "\n"; value_len = 1;
- } else {
- if (value[value_len] == '\r')
- value_len++;
- i_assert(value[value_len] == '\n');
- value_len += (size_t) (value-name) + 1;
+ /* end of headers */
+ write_func(output, "\n", 1);
}
+ message_parse_header_deinit(hdr_ctx);
- if (ctx->write_func(ctx->output, name, value_len) < 0) {
- set_write_error(ctx->storage, ctx->output, ctx->path);
- ctx->failed = TRUE;
- }
+ return !failed;
}
int index_storage_save(struct mail_storage *storage, const char *path,
struct istream *input, struct ostream *output,
header_callback_t *header_callback, void *context)
{
- int (*write_func)(struct ostream *, const void *, size_t);
+ write_func_t *write_func;
const unsigned char *data;
size_t size;
ssize_t ret;
@@ -150,20 +145,8 @@
write_func = getenv("MAIL_SAVE_CRLF") ? write_with_crlf : write_with_lf;
if (header_callback != NULL) {
- struct save_header_context ctx;
-
- memset(&ctx, 0, sizeof(ctx));
- ctx.storage = storage;
- ctx.output = output;
- ctx.path = path;
- ctx.write_func = write_func;
- ctx.header_callback = header_callback;
- ctx.context = context;
-
- message_parse_header(NULL, input, NULL,
- save_header_callback, &ctx);
-
- if (ctx.failed)
+ if (!save_headers(input, output, header_callback,
+ context, write_func))
return FALSE;
}
Index: index-search.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-search.c,v
retrieving revision 1.68
retrieving revision 1.69
diff -u -d -r1.68 -r1.69
--- index-search.c 1 Feb 2003 11:37:22 -0000 1.68
+++ index-search.c 26 Mar 2003 17:29:02 -0000 1.69
@@ -41,8 +41,7 @@
struct mail_search_context *index_context;
struct mail_search_arg *args;
- const unsigned char *name, *value;
- size_t name_len, value_len;
+ struct message_header_line *hdr;
unsigned int custom_header:1;
unsigned int threading:1;
@@ -283,7 +282,7 @@
}
static int search_sent(enum mail_search_arg_type type, const char *search_value,
- const char *sent_value)
+ const unsigned char *sent_value, size_t sent_value_len)
{
time_t search_time, sent_time;
int timezone_offset;
@@ -296,7 +295,7 @@
/* NOTE: Latest IMAP4rev1 draft specifies that timezone is ignored
in searches. sent_time is returned as UTC, so change it. */
- if (!message_date_parse((const unsigned char *) sent_value, (size_t)-1,
+ if (!message_date_parse(sent_value, sent_value_len,
&sent_time, &timezone_offset))
return 0;
sent_time -= timezone_offset * 60;
@@ -404,7 +403,9 @@
case SEARCH_SENTBEFORE:
case SEARCH_SENTON:
case SEARCH_SENTSINCE:
- ret = search_sent(arg->type, arg->value.str, field);
+ ret = search_sent(arg->type, arg->value.str,
+ (const unsigned char *) field,
+ (size_t)-1);
break;
default:
if (arg->value.str[0] == '\0') {
@@ -457,7 +458,6 @@
{
struct search_header_context *ctx = context;
struct header_search_context *hdr_search_ctx;
- size_t len;
int ret;
/* first check that the field name matches to argument. */
@@ -466,41 +466,50 @@
case SEARCH_SENTON:
case SEARCH_SENTSINCE:
/* date is handled differently than others */
- if (ctx->name_len == 4 &&
- memcasecmp(ctx->name, "Date", 4) == 0) {
+ if (strcasecmp(ctx->hdr->name, "Date") == 0) {
+ if (ctx->hdr->continues) {
+ ctx->hdr->use_full_value = TRUE;
+ return;
+ }
ret = search_sent(arg->type, arg->value.str,
- t_strndup(ctx->value, ctx->value_len));
+ ctx->hdr->full_value,
+ ctx->hdr->full_value_len);
ARG_SET_RESULT(arg, ret);
}
return;
case SEARCH_FROM:
- if (ctx->name_len != 4 || memcasecmp(ctx->name, "From", 4) != 0)
+ if (strcasecmp(ctx->hdr->name, "From") != 0)
return;
break;
case SEARCH_TO:
- if (ctx->name_len != 2 || memcasecmp(ctx->name, "To", 2) != 0)
+ if (strcasecmp(ctx->hdr->name, "To") != 0)
return;
break;
case SEARCH_CC:
- if (ctx->name_len != 2 || memcasecmp(ctx->name, "Cc", 2) != 0)
+ if (strcasecmp(ctx->hdr->name, "Cc") != 0)
return;
break;
case SEARCH_BCC:
- if (ctx->name_len != 3 || memcasecmp(ctx->name, "Bcc", 3) != 0)
+ if (strcasecmp(ctx->hdr->name, "Bcc") != 0)
return;
break;
case SEARCH_SUBJECT:
- if (ctx->name_len != 7 ||
- memcasecmp(ctx->name, "Subject", 7) != 0)
+ if (strcasecmp(ctx->hdr->name, "Subject") != 0)
+ return;
+ break;
+ case SEARCH_IN_REPLY_TO:
+ if (strcasecmp(ctx->hdr->name, "In-Reply-To") != 0)
+ return;
+ break;
+ case SEARCH_MESSAGE_ID:
+ if (strcasecmp(ctx->hdr->name, "Message-ID") != 0)
return;
break;
case SEARCH_HEADER:
ctx->custom_header = TRUE;
- len = strlen(arg->hdr_field_name);
- if (ctx->name_len != len ||
- memcasecmp(ctx->name, arg->hdr_field_name, len) != 0)
+ if (strcasecmp(ctx->hdr->name, arg->hdr_field_name) != 0)
return;
case SEARCH_TEXT:
/* TEXT goes through all headers */
@@ -514,6 +523,11 @@
/* we're just testing existence of the field. always matches. */
ret = 1;
} else {
+ if (ctx->hdr->continues) {
+ ctx->hdr->use_full_value = TRUE;
+ return;
+ }
+
t_push();
hdr_search_ctx = search_header_context(ctx->index_context, arg);
@@ -526,14 +540,16 @@
string_t *str;
addr = message_address_parse(data_stack_pool,
- ctx->value, ctx->value_len,
+ ctx->hdr->full_value,
+ ctx->hdr->full_value_len,
0);
- str = t_str_new(ctx->value_len);
+ str = t_str_new(ctx->hdr->value_len);
message_address_write(str, addr);
ret = message_header_search(str_data(str), str_len(str),
hdr_search_ctx) ? 1 : 0;
} else {
- ret = message_header_search(ctx->value, ctx->value_len,
+ ret = message_header_search(ctx->hdr->full_value,
+ ctx->hdr->full_value_len,
hdr_search_ctx) ? 1 : 0;
}
t_pop();
@@ -565,6 +581,8 @@
case SEARCH_BCC:
case SEARCH_SUBJECT:
case SEARCH_HEADER:
+ case SEARCH_IN_REPLY_TO:
+ case SEARCH_MESSAGE_ID:
ARG_SET_RESULT(arg, 0);
break;
default:
@@ -573,32 +591,34 @@
}
static void search_header(struct message_part *part,
- const unsigned char *name, size_t name_len,
- const unsigned char *value, size_t value_len,
- void *context)
+ struct message_header_line *hdr, void *context)
{
struct search_header_context *ctx = context;
- index_mail_parse_header(part, name, name_len, value, value_len,
- ctx->index_context->mail);
+ if (hdr == NULL) {
+ /* end of headers, mark all unknown SEARCH_HEADERs unmatched */
+ mail_search_args_foreach(ctx->args, search_header_unmatch, ctx);
+ return;
+ }
- if ((ctx->custom_header && name_len > 0) ||
- (name_len == 4 && memcasecmp(name, "Date", 4) == 0) ||
- (name_len == 4 && memcasecmp(name, "From", 4) == 0) ||
- (name_len == 2 && memcasecmp(name, "To", 2) == 0) ||
- (name_len == 2 && memcasecmp(name, "Cc", 2) == 0) ||
- (name_len == 3 && memcasecmp(name, "Bcc", 3) == 0) ||
- (name_len == 7 && memcasecmp(name, "Subject", 7) == 0)) {
- ctx->name = name;
- ctx->value = value;
- ctx->name_len = name_len;
- ctx->value_len = value_len;
+ if (hdr->eoh)
+ return;
+
+ index_mail_parse_header(part, hdr, ctx->index_context->mail);
+
+ if (ctx->custom_header ||
+ strcasecmp(hdr->name, "Date") == 0 ||
+ strcasecmp(hdr->name, "From") == 0 ||
+ strcasecmp(hdr->name, "To") == 0 ||
+ strcasecmp(hdr->name, "Cc") == 0 ||
+ strcasecmp(hdr->name, "Bcc") == 0 ||
+ strcasecmp(hdr->name, "Subject") == 0 ||
+ strcasecmp(hdr->name, "In-Reply-To") == 0 ||
+ strcasecmp(hdr->name, "Message-ID") == 0) {
+ ctx->hdr = hdr;
ctx->custom_header = FALSE;
mail_search_args_foreach(ctx->args, search_header_arg, ctx);
- } else if (name_len == 0) {
- /* last header, mark all unknown SEARCH_HEADERs unmatched */
- mail_search_args_foreach(ctx->args, search_header_unmatch, ctx);
}
}
Index: index-storage.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/index-storage.h,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- index-storage.h 5 Mar 2003 01:43:16 -0000 1.34
+++ index-storage.h 26 Mar 2003 17:29:02 -0000 1.35
@@ -8,7 +8,7 @@
typedef int write_func_t(struct ostream *, const void *, size_t);
/* Return -1 = failure, 0 = don't write the header, 1 = write it */
-typedef int header_callback_t(const unsigned char *name, size_t len,
+typedef int header_callback_t(const char *name,
write_func_t *write_func, void *context);
struct index_autosync_file {
More information about the dovecot-cvs
mailing list