summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2010-06-17 14:08:59 +0100
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-06-28 13:01:21 +0100
commit7760b521d0bb094292ec819dbd9f625ada37a6e4 (patch)
treea1f8ff21886f8bed89de12a51e865e3e808b2273
parent8b940c67864de2d342e438e0b4d7c07670fc4bec (diff)
downloadevolution-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.c110
-rw-r--r--camel/providers/imapx/camel-imapx-utils.c10
-rw-r--r--camel/providers/imapx/camel-imapx-utils.h1
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;