[dovecot-cvs] dovecot/src/imap imap-fetch-body.c, 1.18,
1.19 imap-fetch.c, 1.38, 1.39 imap-fetch.h, 1.15, 1.16
cras at dovecot.org
cras at dovecot.org
Fri Mar 18 20:49:56 EET 2005
Update of /var/lib/cvs/dovecot/src/imap
In directory talvi:/tmp/cvs-serv6206
Modified Files:
imap-fetch-body.c imap-fetch.c imap-fetch.h
Log Message:
Send buffered fetch items to client first. Fixes kmail and Thunderbird
issues..
Index: imap-fetch-body.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-fetch-body.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- imap-fetch-body.c 15 Mar 2005 19:01:51 -0000 1.18
+++ imap-fetch-body.c 18 Mar 2005 18:49:53 -0000 1.19
@@ -587,7 +587,8 @@
MAIL_FETCH_STREAM_BODY)) != 0) {
/* we'll need to open the file anyway, don't try to get the
headers from cache. */
- imap_fetch_add_handler(ctx, fetch_body_header_partial, body);
+ imap_fetch_add_handler(ctx, FALSE,
+ fetch_body_header_partial, body);
return TRUE;
}
@@ -599,7 +600,7 @@
}
body->header_ctx = mailbox_header_lookup_init(ctx->box, body->fields);
- imap_fetch_add_handler(ctx, fetch_body_header_fields, body);
+ imap_fetch_add_handler(ctx, FALSE, fetch_body_header_fields, body);
t_pop();
return TRUE;
}
@@ -612,13 +613,13 @@
if (*section == '\0') {
ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER |
MAIL_FETCH_STREAM_BODY;
- imap_fetch_add_handler(ctx, fetch_body, body);
+ imap_fetch_add_handler(ctx, FALSE, fetch_body, body);
return TRUE;
}
if (strcmp(section, "TEXT") == 0) {
ctx->fetch_data |= MAIL_FETCH_STREAM_BODY;
- imap_fetch_add_handler(ctx, fetch_body, body);
+ imap_fetch_add_handler(ctx, FALSE, fetch_body, body);
return TRUE;
}
@@ -626,7 +627,7 @@
/* exact header matches could be cached */
if (section[6] == '\0') {
ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER;
- imap_fetch_add_handler(ctx, fetch_body, body);
+ imap_fetch_add_handler(ctx, FALSE, fetch_body, body);
return TRUE;
}
@@ -636,8 +637,8 @@
if (strncmp(section, "HEADER.FIELDS.NOT ", 18) == 0 &&
fetch_body_header_fields_check(section+18)) {
- imap_fetch_add_handler(ctx, fetch_body_header_partial,
- body);
+ imap_fetch_add_handler(ctx, FALSE,
+ fetch_body_header_partial, body);
return TRUE;
}
} else if (*section >= '0' && *section <= '9') {
@@ -655,7 +656,8 @@
fetch_body_header_fields_check(section+14)) ||
(strncmp(section, "HEADER.FIELDS.NOT ", 18) == 0 &&
fetch_body_header_fields_check(section+18))) {
- imap_fetch_add_handler(ctx, fetch_body_mime, body);
+ imap_fetch_add_handler(ctx, FALSE,
+ fetch_body_mime, body);
return TRUE;
}
}
@@ -926,24 +928,24 @@
ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER |
MAIL_FETCH_STREAM_BODY;
ctx->flags_update_seen = TRUE;
- imap_fetch_add_handler(ctx, fetch_rfc822, NULL);
+ imap_fetch_add_handler(ctx, FALSE, fetch_rfc822, NULL);
return TRUE;
}
if (strcmp(name+6, ".SIZE") == 0) {
ctx->fetch_data |= MAIL_FETCH_VIRTUAL_SIZE;
- imap_fetch_add_handler(ctx, fetch_rfc822_size, NULL);
+ imap_fetch_add_handler(ctx, TRUE, fetch_rfc822_size, NULL);
return TRUE;
}
if (strcmp(name+6, ".HEADER") == 0) {
ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER;
- imap_fetch_add_handler(ctx, fetch_rfc822_header, NULL);
+ imap_fetch_add_handler(ctx, FALSE, fetch_rfc822_header, NULL);
return TRUE;
}
if (strcmp(name+6, ".TEXT") == 0) {
ctx->fetch_data |= MAIL_FETCH_STREAM_BODY;
ctx->flags_update_seen = TRUE;
- imap_fetch_add_handler(ctx, fetch_rfc822_text, NULL);
+ imap_fetch_add_handler(ctx, FALSE, fetch_rfc822_text, NULL);
return TRUE;
}
Index: imap-fetch.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-fetch.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- imap-fetch.c 15 Mar 2005 19:01:51 -0000 1.38
+++ imap-fetch.c 18 Mar 2005 18:49:53 -0000 1.39
@@ -93,22 +93,32 @@
ctx->cur_str = str_new(default_pool, 8192);
ctx->all_headers_buf = buffer_create_dynamic(cmd->pool, 128);
- ctx->handlers = buffer_create_dynamic(cmd->pool, 128);
+ ARRAY_CREATE(&ctx->handlers, cmd->pool,
+ struct imap_fetch_context_handler, 16);
ctx->line_finished = TRUE;
return ctx;
}
-void imap_fetch_add_handler(struct imap_fetch_context *ctx,
+void imap_fetch_add_handler(struct imap_fetch_context *ctx, int buffered,
imap_fetch_handler_t *handler, void *context)
{
+ /* partially because of broken clients, but also partially because
+ it potentially can make client implementations faster, we have a
+ buffered parameter which basically means that the handler promises
+ to write the output in ctx->cur_str. The cur_str is then sent to
+ client before calling any non-buffered handlers.
+
+ We try to keep the handler registration order the same as the
+ client requested them. This is especially useful to get UID
+ returned first, which some clients rely on..
+ */
const struct imap_fetch_context_handler *handlers;
struct imap_fetch_context_handler h;
- size_t i, size;
+ unsigned int i, size;
if (context == NULL) {
/* don't allow duplicate handlers */
- handlers = buffer_get_data(ctx->handlers, &size);
- size /= sizeof(*handlers);
+ handlers = array_get(&ctx->handlers, &size);
for (i = 0; i < size; i++) {
if (handlers[i].handler == handler &&
@@ -120,8 +130,15 @@
memset(&h, 0, sizeof(h));
h.handler = handler;
h.context = context;
+ h.buffered = buffered;
- buffer_append(ctx->handlers, &h, sizeof(h));
+ if (!buffered)
+ array_append(&ctx->handlers, &h, 1);
+ else {
+ array_insert(&ctx->handlers, ctx->buffered_handlers_count,
+ &h, 1);
+ ctx->buffered_handlers_count++;
+ }
}
void imap_fetch_begin(struct imap_fetch_context *ctx,
@@ -158,10 +175,34 @@
mailbox_search_init(ctx->trans, NULL, search_arg, NULL);
}
+static int imap_fetch_flush_buffer(struct imap_fetch_context *ctx)
+{
+ const unsigned char *data;
+ size_t len;
+
+ i_assert(ctx->first);
+
+ data = str_data(ctx->cur_str);
+ len = str_len(ctx->cur_str);
+
+ /* there's an extra space at the end if we added any fetch items
+ to buffer */
+ if (data[len-1] == ' ') {
+ len--;
+ ctx->first = FALSE;
+ }
+
+ if (o_stream_send(ctx->client->output, data, len) < 0)
+ return -1;
+
+ str_truncate(ctx->cur_str, 0);
+ return 0;
+}
+
int imap_fetch(struct imap_fetch_context *ctx)
{
const struct imap_fetch_context_handler *handlers;
- size_t size;
+ unsigned int size;
int ret;
if (ctx->cont_handler != NULL) {
@@ -184,9 +225,7 @@
ctx->cur_handler++;
}
- handlers = buffer_get_data(ctx->handlers, &size);
- size /= sizeof(*handlers);
-
+ handlers = array_get(&ctx->handlers, &size);
for (;;) {
if (o_stream_get_buffer_used_size(ctx->client->output) >=
CLIENT_OUTPUT_OPTIMAL_SIZE) {
@@ -208,18 +247,19 @@
str_printfa(ctx->cur_str, "* %u FETCH (",
ctx->cur_mail->seq);
- if (o_stream_send(ctx->client->output,
- str_data(ctx->cur_str),
- str_len(ctx->cur_str)) < 0)
- return -1;
-
- str_truncate(ctx->cur_str, 0);
- str_append_c(ctx->cur_str, ' ');
ctx->first = TRUE;
ctx->line_finished = FALSE;
}
for (; ctx->cur_handler < size; ctx->cur_handler++) {
+ if (str_len(ctx->cur_str) > 0 &&
+ !handlers[ctx->cur_handler].buffered) {
+ /* first non-buffered handler.
+ flush the buffer. */
+ if (imap_fetch_flush_buffer(ctx) < 0)
+ return -1;
+ }
+
t_push();
ret = handlers[ctx->cur_handler].
handler(ctx, ctx->cur_mail,
@@ -244,14 +284,11 @@
ctx->cur_offset = 0;
}
- if (str_len(ctx->cur_str) > 1) {
- if (o_stream_send(ctx->client->output,
- str_data(ctx->cur_str) + ctx->first,
- str_len(ctx->cur_str) - 1 -
- ctx->first) < 0)
+ if (str_len(ctx->cur_str) > 0) {
+ /* no non-buffered handlers */
+ if (imap_fetch_flush_buffer(ctx) < 0)
return -1;
}
- str_truncate(ctx->cur_str, 0);
ctx->line_finished = TRUE;
if (o_stream_send(ctx->client->output, ")\r\n", 3) < 0)
@@ -327,7 +364,7 @@
{
if (name[4] == '\0') {
ctx->fetch_data |= MAIL_FETCH_IMAP_BODY;
- imap_fetch_add_handler(ctx, fetch_body, NULL);
+ imap_fetch_add_handler(ctx, FALSE, fetch_body, NULL);
return TRUE;
}
return fetch_body_section_init(ctx, name, args);
@@ -362,7 +399,7 @@
struct imap_arg **args __attr_unused__)
{
ctx->fetch_data |= MAIL_FETCH_IMAP_BODYSTRUCTURE;
- imap_fetch_add_handler(ctx, fetch_bodystructure, NULL);
+ imap_fetch_add_handler(ctx, FALSE, fetch_bodystructure, NULL);
return TRUE;
}
@@ -394,7 +431,7 @@
struct imap_arg **args __attr_unused__)
{
ctx->fetch_data |= MAIL_FETCH_IMAP_ENVELOPE;
- imap_fetch_add_handler(ctx, fetch_envelope, NULL);
+ imap_fetch_add_handler(ctx, FALSE, fetch_envelope, NULL);
return TRUE;
}
@@ -428,7 +465,7 @@
{
ctx->flags_have_handler = TRUE;
ctx->fetch_data |= MAIL_FETCH_FLAGS;
- imap_fetch_add_handler(ctx, fetch_flags, NULL);
+ imap_fetch_add_handler(ctx, TRUE, fetch_flags, NULL);
return TRUE;
}
@@ -452,7 +489,7 @@
struct imap_arg **args __attr_unused__)
{
ctx->fetch_data |= MAIL_FETCH_RECEIVED_DATE;
- imap_fetch_add_handler(ctx, fetch_internaldate, NULL);
+ imap_fetch_add_handler(ctx, TRUE, fetch_internaldate, NULL);
return TRUE;
}
@@ -467,7 +504,7 @@
const char *name __attr_unused__,
struct imap_arg **args __attr_unused__)
{
- imap_fetch_add_handler(ctx, fetch_uid, NULL);
+ imap_fetch_add_handler(ctx, TRUE, fetch_uid, NULL);
return TRUE;
}
Index: imap-fetch.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-fetch.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- imap-fetch.h 15 Mar 2005 19:01:51 -0000 1.15
+++ imap-fetch.h 18 Mar 2005 18:49:54 -0000 1.16
@@ -19,6 +19,7 @@
struct imap_fetch_context_handler {
imap_fetch_handler_t *handler;
void *context;
+ int buffered;
};
struct imap_fetch_context {
@@ -34,7 +35,8 @@
buffer_t *all_headers_buf;
struct mailbox_header_lookup_ctx *all_headers_ctx;
- buffer_t *handlers;
+ array_t ARRAY_DEFINE(handlers, struct imap_fetch_context_handler);
+ unsigned int buffered_handlers_count;
struct mail *cur_mail;
unsigned int cur_handler;
@@ -61,7 +63,7 @@
void imap_fetch_handlers_register(const struct imap_fetch_handler *handlers,
size_t count);
-void imap_fetch_add_handler(struct imap_fetch_context *ctx,
+void imap_fetch_add_handler(struct imap_fetch_context *ctx, int buffered,
imap_fetch_handler_t *handler, void *context);
struct imap_fetch_context *imap_fetch_init(struct client_command_context *cmd);
More information about the dovecot-cvs
mailing list