# HG changeset patch # User Timo Sirainen # Date 1257186889 18000 # Node ID 0dc82e18530daba409ef2d0f03fd9750b7b38574 # Parent 673a017081af438b96a4a65231563fa8bbf8d68d imap proxy: Always send changed capability to client. The original code did it only when client had used CAPABILITY command. Now it's also sent in tagged reply to login/authenticate command if the remote server didn't already add it. diff -r 673a017081af -r 0dc82e18530d src/imap-login/imap-proxy.c --- a/src/imap-login/imap-proxy.c Fri Oct 30 15:06:46 2009 -0400 +++ b/src/imap-login/imap-proxy.c Mon Nov 02 13:34:49 2009 -0500 @@ -108,19 +108,11 @@ } static void -client_send_capability_if_needed(struct imap_client *client, string_t *str, - const char *capability) +client_send_capability_if_needed(string_t *str, const char *capability) { const char *const *backend_capabilities; const char *const *proxy_capabilities; - if (!client->client_ignores_capability_resp_code || capability == NULL) - return; - - /* reset this so that we don't re-send the CAPABILITY in case server - sends it multiple times */ - client->client_ignores_capability_resp_code = FALSE; - /* client has used CAPABILITY command, so it didn't understand the capabilities in the banner. if backend server has different capabilities than we advertised already, there's a problem. @@ -131,17 +123,13 @@ proxy_capabilities = capabilities_strip_prelogin(t_strsplit(capability_string, " ")); - if (str_array_icmp(backend_capabilities, proxy_capabilities)) - return; - - str_printfa(str, "* CAPABILITY %s\r\n", capability); + if (!str_array_icmp(backend_capabilities, proxy_capabilities)) + str_printfa(str, "* CAPABILITY %s\r\n", capability); } static void proxy_write_login(struct imap_client *client, string_t *str) { - if (client->client_ignores_capability_resp_code) - str_append(str, "C CAPABILITY\r\n"); - + str_append(str, "C CAPABILITY\r\n"); if (client->proxy_master_user == NULL) { /* logging in normally - use LOGIN command */ str_append(str, "L LOGIN "); @@ -203,10 +191,40 @@ return 0; } +static void +client_send_login_reply(struct imap_client *client, string_t *str, + const char *line) +{ + const char *capability; + bool tagged_capability; + + capability = client->proxy_backend_capability; + tagged_capability = strncasecmp(line, "[CAPABILITY ", 12) == 0; + if (tagged_capability) + capability = t_strcut(line + 12, ']'); + + if (client->client_ignores_capability_resp_code && capability != NULL) + client_send_capability_if_needed(str, capability); + str_append(str, client->cmd_tag); + str_append(str, " OK "); + if (!client->client_ignores_capability_resp_code && + !tagged_capability && capability != NULL) { + str_printfa(str, "[CAPABILITY %s] ", capability); + if (*line == '[') { + /* we need to send the capability. + skip over this resp-code */ + while (*line != ']' && *line != '\0') + line++; + if (*line == ' ') line++; + } + } + str_append(str, line); + str_append(str, "\r\n"); +} + static int proxy_input_line(struct imap_client *client, const char *line) { struct ostream *output; - const char *capability; string_t *str; i_assert(!client->destroyed); @@ -257,15 +275,8 @@ return 1; } else if (strncmp(line, "L OK ", 5) == 0) { /* Login successful. Send this line to client. */ - capability = client->proxy_backend_capability; - if (strncmp(line + 5, "[CAPABILITY ", 12) == 0) - capability = t_strcut(line + 5 + 12, ']'); - str = t_str_new(128); - client_send_capability_if_needed(client, str, capability); - str_append(str, client->cmd_tag); - str_append(str, line + 1); - str_append(str, "\r\n"); + client_send_login_reply(client, str, line + 5); (void)o_stream_send(client->output, str_data(str), str_len(str));