diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2010-06-17 14:08:59 +0100 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-06-28 13:01:21 +0100 |
commit | 7760b521d0bb094292ec819dbd9f625ada37a6e4 (patch) | |
tree | a1f8ff21886f8bed89de12a51e865e3e808b2273 | |
parent | 8b940c67864de2d342e438e0b4d7c07670fc4bec (diff) | |
download | evolution-data-server-7760b521d0bb094292ec819dbd9f625ada37a6e4.tar.gz |
Fix handling of unsolicited [CAPABILITY xxx] report in server greeting.
Fix up imapx_untagged() and imap_parse_status() to handle capabilities,
and use imapx_untagged() to read the server greeting.
Unify the greeting handling for the process and socket connections, and
don't re-fetch the capabilities immediately if we have them.
Handle incoming lines of noise before the greeting.
(cherry picked from commit 4fcd06b696ad30804fcb5a140a9253f9cea6114c)
-rw-r--r-- | camel/providers/imapx/camel-imapx-server.c | 110 | ||||
-rw-r--r-- | camel/providers/imapx/camel-imapx-utils.c | 10 | ||||
-rw-r--r-- | camel/providers/imapx/camel-imapx-utils.h | 1 |
3 files changed, 72 insertions, 49 deletions
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c index 649d6a2f2..3c1a1f649 100644 --- a/camel/providers/imapx/camel-imapx-server.c +++ b/camel/providers/imapx/camel-imapx-server.c @@ -1394,11 +1394,18 @@ imapx_untagged(CamelIMAPXServer *imap, CamelException *ex) } break; } - case IMAPX_BYE: case IMAPX_OK: case IMAPX_NO: case IMAPX_BAD: case IMAPX_PREAUTH: + case IMAPX_PREAUTH: + c(printf("preauthenticated\n")); + if (imap->state < IMAPX_AUTHENTICATED) + imap->state = IMAPX_AUTHENTICATED; + /* fall through... */ + case IMAPX_BYE: case IMAPX_OK: case IMAPX_NO: case IMAPX_BAD: /* TODO: validate which ones of these can happen as unsolicited responses */ /* TODO: handle bye/preauth differently */ camel_imapx_stream_ungettoken(imap->stream, tok, token, len); sinfo = imapx_parse_status(imap->stream, ex); + if (camel_exception_is_set(ex)) + return -1; camel_object_trigger_event(imap, "status", sinfo); switch (sinfo->condition) { case IMAPX_READ_WRITE: @@ -1424,6 +1431,14 @@ imapx_untagged(CamelIMAPXServer *imap, CamelException *ex) case IMAPX_PARSE: c(printf("PARSE: %s\n", sinfo->text)); break; + case IMAPX_CAPABILITY: + if (sinfo->u.cinfo) { + if (imap->cinfo) + imapx_free_capability(imap->cinfo); + imap->cinfo = sinfo->u.cinfo; + c(printf("got capability flags %08x\n", imap->cinfo->capa)); + } + break; default: break; } @@ -2114,15 +2129,12 @@ imapx_select (CamelIMAPXServer *is, CamelFolder *folder, gboolean forced, CamelE static gboolean connect_to_server_process (CamelIMAPXServer *is, const gchar *cmd, CamelException *ex) { - CamelIMAPXCommand *ic; CamelStream *cmd_stream; gint ret, i = 0; gchar *buf; gchar *cmd_copy; gchar *full_cmd; gchar *child_env[7]; - guchar *buffer = NULL; - guint len; /* Put full details in the environment, in case the connection program needs them */ @@ -2214,36 +2226,6 @@ connect_to_server_process (CamelIMAPXServer *is, const gchar *cmd, CamelExceptio camel_object_unref(cmd_stream); is->is_process_stream = TRUE; - camel_imapx_stream_gets (is->stream, &buffer, &len); - e(printf("Got greeting '%.*s'\n", len, buffer)); - - if (!buffer) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - "No response from server.\n"); - return FALSE; - } else if (!strncmp((gchar *)buffer, "* PREAUTH", 9)) { - is->state = IMAPX_AUTHENTICATED; - } else if (strncmp((gchar *)buffer, "* OK", 4)) { - camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, - "Unrecognised greeting from server: %.*s\n", - len, buffer); - return FALSE; - } - - ic = camel_imapx_command_new("CAPABILITY", NULL, "CAPABILITY"); - imapx_command_run(is, ic); - - if (camel_exception_is_set (ic->ex) || ic->status->result != IMAPX_OK) { - if (!camel_exception_is_set (ic->ex)) - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, "%s", ic->status->text); - else - camel_exception_xfer (ex, ic->ex); - - camel_imapx_command_free(ic); - return FALSE; - } - camel_imapx_command_free(ic); - return TRUE; } #endif /* G_OS_WIN32 */ @@ -2258,8 +2240,9 @@ imapx_connect_to_server (CamelIMAPXServer *is, CamelException *ex) #ifdef HAVE_SSL const gchar *mode; #endif - guchar *buffer = NULL; guint len; + guchar *token; + gint tok; const gchar *serv; const gchar *port = NULL; struct addrinfo *ai, hints = { 0 }; @@ -2270,8 +2253,12 @@ imapx_connect_to_server (CamelIMAPXServer *is, CamelException *ex) if (camel_url_get_param(is->url, "use_command") && (command = camel_url_get_param(is->url, "command"))) { + camel_exception_clear(ex); connect_to_server_process(is, command, ex); - goto exit; + if (camel_exception_is_set (ex)) + goto exit; + else + goto connected; } #endif if (is->url->port) { @@ -2343,22 +2330,48 @@ imapx_connect_to_server (CamelIMAPXServer *is, CamelException *ex) sockopt.value.keep_alive = TRUE; camel_tcp_stream_setsockopt ((CamelTcpStream *)tcp_stream, &sockopt); - camel_imapx_stream_gets (is->stream, &buffer, &len); - e(printf("Got greeting '%.*s'\n", len, buffer)); + connected: + while (1) { + // poll ? wait for other stuff? loop? + if (camel_application_is_exiting || is->parser_quit) { + camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, + "Connection to server cancelled\n"); + return FALSE; + } + + tok = camel_imapx_stream_token (is->stream, &token, &len, ex); + if (camel_exception_is_set (ex)) { + return FALSE; + } - ic = camel_imapx_command_new("CAPABILITY", NULL, "CAPABILITY"); - imapx_command_run(is, ic); + if (tok == '*') { + imapx_untagged (is, ex); + break; + } + camel_imapx_stream_ungettoken(is->stream, tok, token, len); + camel_imapx_stream_text (is->stream, &token, ex); + if (camel_exception_is_set (ex)) { + return FALSE; + } + e(printf("Got unexpected line before greeting: '%s'\n", token)); + g_free(token); + } - if (camel_exception_is_set (ic->ex) || ic->status->result != IMAPX_OK) { - if (!camel_exception_is_set (ic->ex)) - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, "%s", ic->status->text); - else - camel_exception_xfer (ex, ic->ex); + if (!is->cinfo) { + ic = camel_imapx_command_new("CAPABILITY", NULL, "CAPABILITY"); + imapx_command_run(is, ic); + if (camel_exception_is_set (ic->ex) || ic->status->result != IMAPX_OK) { + if (!camel_exception_is_set (ic->ex)) + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, "%s", ic->status->text); + else + camel_exception_xfer (ex, ic->ex); + + camel_imapx_command_free(ic); + return FALSE; + } camel_imapx_command_free(ic); - goto exit; } - camel_imapx_command_free(ic); #ifdef HAVE_SSL if (ssl_mode == 2) @@ -2436,7 +2449,7 @@ imapx_reconnect (CamelIMAPXServer *is, CamelException *ex) goto exception; if (is->state == IMAPX_AUTHENTICATED) - break; + goto preauthed; if (!authtype && service->url->authmech) { if (is->cinfo && !g_hash_table_lookup (is->cinfo->auth_types, service->url->authmech)) { @@ -2539,6 +2552,7 @@ imapx_reconnect (CamelIMAPXServer *is, CamelException *ex) is->state = IMAPX_AUTHENTICATED; + preauthed: if (((CamelIMAPXStore *)is->store)->rec_options & IMAPX_USE_IDLE) is->use_idle = TRUE; else diff --git a/camel/providers/imapx/camel-imapx-utils.c b/camel/providers/imapx/camel-imapx-utils.c index af24e3468..72ff19866 100644 --- a/camel/providers/imapx/camel-imapx-utils.c +++ b/camel/providers/imapx/camel-imapx-utils.c @@ -406,8 +406,13 @@ imapx_parse_capability(CamelIMAPXStream *stream, CamelException *ex) cinfo->auth_types = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL); /* FIXME: handle auth types */ - while (!camel_exception_is_set (ex) && (tok = camel_imapx_stream_token(stream, &token, &len, ex)) != '\n') { + while ((tok = camel_imapx_stream_token(stream, &token, &len, ex)) != '\n' && + !camel_exception_is_set (ex)) { switch (tok) { + case ']': + /* Put it back so that imapx_untagged() isn't unhappy */ + camel_imapx_stream_ungettoken(stream, tok, token, len); + return cinfo; case 43: token = (guchar *) g_strconcat ((gchar *)token, "+", NULL); free_token = TRUE; @@ -1636,6 +1641,9 @@ imapx_parse_status(CamelIMAPXStream *is, CamelException *ex) case IMAPX_UNSEEN: sinfo->u.unseen = camel_imapx_stream_number(is, ex); break; + case IMAPX_CAPABILITY: + sinfo->u.cinfo = imapx_parse_capability(is, ex); + break; default: sinfo->condition = IMAPX_UNKNOWN; d(printf("Got unknown response code: %s: ignored\n", token)); diff --git a/camel/providers/imapx/camel-imapx-utils.h b/camel/providers/imapx/camel-imapx-utils.h index 97a437e3a..9f2c4c3ae 100644 --- a/camel/providers/imapx/camel-imapx-utils.h +++ b/camel/providers/imapx/camel-imapx-utils.h @@ -159,6 +159,7 @@ struct _status_info { GPtrArray *uids; GPtrArray *copied_uids; } copyuid; + struct _capability_info *cinfo; } u; gchar *text; |