On Fri, 2010-11-19 at 11:45 +0200, Axel Thimm wrote: > evolution has a bug when it comes to closing and IDLE' connection: > > https://bugzilla.gnome.org/show_bug.cgi?id=628515 > > evolution does not send a DONE command, and dovecot properly answers > with an error. evolution ignores this and seems to wait on another > response. > > Timo, do you think there could be a setting for tolerating missing > DONEs? Thanks!
Well .. the attached patch should do it, but looks like a lot more code just to fix a client.. I also tested that Cyrus at least works the same way as Dovecot.
diff -r 3a93121f652a src/imap/cmd-idle.c --- a/src/imap/cmd-idle.c Mon Nov 22 18:35:07 2010 +0000 +++ b/src/imap/cmd-idle.c Mon Nov 22 18:58:15 2010 +0000 @@ -55,10 +55,27 @@ client_command_free(&ctx->cmd); } +static int idle_is_done(const unsigned char *data, size_t size) +{ + if (i_memcasecmp(data, "DONE", I_MIN(size, 4)) != 0) + return -1; + if (size > 4) { + if (data[4] == '\n') + return 5; + if (data[4] != '\r') + return -1; + if (size > 5) + return data[5] == '\n' ? 6 : -1; + } + return 0; +} + static void idle_client_input_more(struct cmd_idle_context *ctx) { struct client *client = ctx->client; - char *line; + const unsigned char *data; + size_t size; + int ret; client->last_input = ioloop_time; timeout_reset(client->to_idle); @@ -82,13 +99,17 @@ return; } - while ((line = i_stream_next_line(client->input)) != NULL) { - if (client->input_skip_line) - client->input_skip_line = FALSE; - else { - idle_finish(ctx, strcasecmp(line, "DONE") == 0, TRUE); - break; - } + if (client->input_skip_line) { + if (i_stream_next_line(client->input) == NULL) + return; + client->input_skip_line = FALSE; + } + + data = i_stream_get_data(client->input, &size); + if ((ret = idle_is_done(data, size)) != 0) { + idle_finish(ctx, ret > 0, TRUE); + if (ret > 0) + i_stream_skip(client->input, ret); } if (!client->disconnected && !client->handling_input) client_continue_pending_input(client);