From e9112cf496ef8dd380ac030624b1fbda2b0d8c3d Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Mon, 24 Jul 2000 01:37:43 +0000 Subject: Made it a little more forgiving. Also set current_folder to NULL as there 2000-07-23 Jeffrey Stedfast * providers/imap/camel-imap-store.c (imap_disconnect): Made it a little more forgiving. Also set current_folder to NULL as there is no selected folder after a disconnect. (stream_is_alive): Detects whether or not a socket is "alive" (camel_imap_command_extended): Use stream_is_alive() to aid in the detection of a disconnected state. svn path=/trunk/; revision=4288 --- camel/ChangeLog | 122 +++++++++++++++++-------------- camel/providers/imap/camel-imap-folder.c | 44 +++++------ camel/providers/imap/camel-imap-store.c | 98 +++++++++++++++++-------- camel/providers/imap/camel-imap-store.h | 2 +- 4 files changed, 159 insertions(+), 107 deletions(-) diff --git a/camel/ChangeLog b/camel/ChangeLog index bd79988c7d..d174136f6a 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,88 +1,104 @@ +2000-07-23 Jeffrey Stedfast + + * providers/imap/camel-imap-store.c (imap_disconnect): Made it a + little more forgiving. Also set current_folder to NULL as there is + no selected folder after a disconnect. + (stream_is_alive): Detects whether or not a socket is "alive" + (camel_imap_command_extended): Use stream_is_alive() to aid in the + detection of a disconnected state. + 2000-07-22 Jeffrey Stedfast - * providers/imap/camel-imap-store.c (get_folder): Clear CamelExceptions when - appropriate (eg when folder is marked as \NoSelect). Still needs some - cleanup and perhaps Dan will have a better way of doing this as this seems - like a messy way of handling this. + * providers/imap/camel-imap-store.c (get_folder): Clear + CamelExceptions when appropriate (eg when folder is marked as + \NoSelect). Still needs some cleanup and perhaps Dan will have a + better way of doing this as this seems like a messy way of + handling this. - * providers/imap/camel-imap-folder.c (imap_get_uids): Took out some debug - statements as they are no longer needed. + * providers/imap/camel-imap-folder.c (imap_get_uids): Took out + some debug statements as they are no longer needed. 2000-07-21 Jeffrey Stedfast - * providers/imap/camel-imap-folder.c (imap_get_subfolder_names): Updated to - not strip out subfolders that are marked as \NoSelect because this will be - correctly handled in store->get_folder from now on. + * providers/imap/camel-imap-folder.c (imap_get_subfolder_names): + Updated to not strip out subfolders that are marked as \NoSelect + because this will be correctly handled in store->get_folder from + now on. - * providers/imap/camel-imap-store.c (folder_is_selectable): New convenience - function for use in get_folder(). - (parse_list_response): Now takes a char **flags argument which is needed by - folder_is_selectable(). - (imap_connect): Updated to reflect changes to parse_list_response(). + * providers/imap/camel-imap-store.c (folder_is_selectable): New + convenience function for use in get_folder(). + (parse_list_response): Now takes a char **flags argument which is + needed by folder_is_selectable(). + (imap_connect): Updated to reflect changes to + parse_list_response(). 2000-07-21 Jeffrey Stedfast - * providers/imap/camel-imap-stream.c (stream_read): Updated with some of the - same fixes I've made to camel-imap-folder.c like recalculating message part - lengths. + * providers/imap/camel-imap-stream.c (stream_read): Updated with + some of the same fixes I've made to camel-imap-folder.c like + recalculating message part lengths. - * providers/imap/camel-imap-store.c (camel_imap_command_extended): Rewrote - the code to check for "* %d RECENT". Still needs to be modified, but should - no longer cause an infinite loop by detecting mis-detecting RECENT messages. + * providers/imap/camel-imap-store.c (camel_imap_command_extended): + Rewrote the code to check for "* %d RECENT". Still needs to be + modified, but should no longer cause an infinite loop by detecting + mis-detecting RECENT messages. 2000-07-20 Jeffrey Stedfast - * providers/imap/camel-imap-folder.c (imap_get_summary): - (imap_get_message_info): Oops. Fix UID parser to allow 0 and 9 to be in - the range of valid UID chars. + * providers/imap/camel-imap-folder.c (imap_get_summary): + (imap_get_message_info): Oops. Fix UID parser to allow 0 and 9 to + be in the range of valid UID chars. 2000-07-19 Jeffrey Stedfast - * providers/imap/camel-imap-folder.c: General cleanup working towards - getting Actions->Expunge working correctly. + * providers/imap/camel-imap-folder.c: General cleanup working + towards getting Actions->Expunge working correctly. - * providers/imap/camel-imap-store.c (cammel_imap_command_extended): Added - code to look for "* %d RECENT" and to emit the folder_changed signal if - there are any recent messages. Note: this is a hack and needs to be rewritten + * providers/imap/camel-imap-store.c + (cammel_imap_command_extended): Added code to look for "* %d + RECENT" and to emit the folder_changed signal if there are any + recent messages. Note: this is a hack and needs to be rewritten badly. 2000-07-19 Jeffrey Stedfast - * providers/imap/camel-imap-folder.c (imap_get_summary): If the folder's - message count is not the same as the number of summaries, free the old - summary and create a new summary. + * providers/imap/camel-imap-folder.c (imap_get_summary): If the + folder's message count is not the same as the number of summaries, + free the old summary and create a new summary. 2000-07-18 Jeffrey Stedfast - * providers/imap/camel-imap-folder.c (camel_imap_folder_class_init): Added - in imap_[g,s]et_message_user_flag() methods + * providers/imap/camel-imap-folder.c + (camel_imap_folder_class_init): Added in + imap_[g,s]et_message_user_flag() methods (imap_get_message_info): Rewrote to use the more efficient way of - downloading summary information and also added a UID comparison so that - if the UID requested doesn't match the UID received, it returns NULL. - FIXME: When the mailer gets NULL when it requested message info, it - seems that it displays a row for that message and when you try and select - the blank row, it segfaults. + downloading summary information and also added a UID comparison so + that if the UID requested doesn't match the UID received, it + returns NULL. FIXME: When the mailer gets NULL when it requested + message info, it seems that it displays a row for that message and + when you try and select the blank row, it segfaults. - * providers/imap/camel-imap-store.c (get_folder): Oops, this should not be - checking against "/", it should be checking against dir_sep. + * providers/imap/camel-imap-store.c (get_folder): Oops, this + should not be checking against "/", it should be checking against + dir_sep. - * providers/imap/camel-imap-folder.c (imap_parse_subfolder_line): Updated - to trim out the leading namespace. - (imap_get_subfolder_names): Let the subfolder parser trim the namespace - off the folder name. + * providers/imap/camel-imap-folder.c (imap_parse_subfolder_line): + Updated to trim out the leading namespace. + (imap_get_subfolder_names): Let the subfolder parser trim the + namespace off the folder name. 2000-07-17 Jeffrey Stedfast - * providers/imap/camel-imap-store.c (imap_disconnect): Send a "LOGOUT" - command. + * providers/imap/camel-imap-store.c (imap_disconnect): Send a + "LOGOUT" command. - * providers/imap/camel-imap-folder.c (imap_get_message): Hacks to get - IMAP code to work with CommunigatePro and MS Exchange (and any other - servers that send back a UID at the end of each FETCH inside of the main - body of the message part). - (imap_sync): Un-#if 0 the code that sets the flags on the IMAP server - for messages that have changed. Oops, don't mask with DELETED to find out - if the message has been answered ;-) + * providers/imap/camel-imap-folder.c (imap_get_message): Hacks to + get IMAP code to work with CommunigatePro and MS Exchange (and any + other servers that send back a UID at the end of each FETCH inside + of the main body of the message part). + (imap_sync): Un-#if 0 the code that sets the flags on the IMAP + server for messages that have changed. Oops, don't mask with + DELETED to find out if the message has been answered ;-) (imap_expunge): sync before expunging. 2000-07-16 Jeffrey Stedfast diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c index 28cf4a848d..1093005376 100644 --- a/camel/providers/imap/camel-imap-folder.c +++ b/camel/providers/imap/camel-imap-folder.c @@ -786,14 +786,14 @@ imap_delete_message (CamelFolder *folder, const gchar *uid, CamelException *ex) static CamelMimeMessage * imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex) { - CamelStream *msgstream; + CamelStream *msgstream = NULL; /*CamelStreamFilter *f_stream;*/ /*CamelMimeFilter *filter;*/ - CamelMimeMessage *msg; + CamelMimeMessage *msg = NULL; /*CamelMimePart *part;*/ - gchar *result, *header, *body, *mesg, *p, *q; - int status, part_len; - + gchar *result, *header = NULL, *body = NULL, *mesg = NULL, *p = NULL, *q = NULL; + int status = 0, part_len = 0; + status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), folder, &result, "UID FETCH %s BODY.PEEK[HEADER]", uid); @@ -808,20 +808,20 @@ imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex) g_free (result); return camel_mime_message_new (); } - + for (p = result; *p && *p != '{' && *p != '\n'; p++); if (*p != '{') { g_free (result); return camel_mime_message_new (); } - - part_len = atoi (p + 1); + + part_len = atoi (p + 1); for ( ; *p && *p != '\n'; p++); if (*p != '\n') { g_free (result); return camel_mime_message_new (); } - + /* calculate the new part-length */ for (q = p; *q && (q - p) <= part_len; q++) { if (*q == '\n') @@ -829,15 +829,15 @@ imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex) } /* FIXME: This is a hack for IMAP daemons that send us a UID at the end of each FETCH */ for (q--, part_len--; q > p && *(q-1) != '\n'; q--, part_len--); - - header = g_strndup (p, part_len + 1); + header = g_strndup (p, part_len + 1); + g_free (result); d(fprintf (stderr, "*** We got the header ***\n")); - + status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), folder, &result, "UID FETCH %s BODY[TEXT]", uid); - + if (!result || status != CAMEL_IMAP_OK) { CamelService *service = CAMEL_SERVICE (folder->parent_store); @@ -850,14 +850,14 @@ imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex) g_free (header); return camel_mime_message_new (); } - + for (p = result; *p && *p != '{' && *p != '\n'; p++); if (*p != '{') { g_free (result); g_free (header); return camel_mime_message_new (); } - + part_len = atoi (p + 1); for ( ; *p && *p != '\n'; p++); if (*p != '\n') { @@ -865,7 +865,7 @@ imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex) g_free (header); return camel_mime_message_new (); } - + /* calculate the new part-length */ for (q = p; *q && (q - p) <= part_len; q++) { if (*q == '\n') @@ -873,19 +873,19 @@ imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex) } /* FIXME: This is a hack for IMAP daemons that send us a UID at the end of each FETCH */ for ( ; q > p && *(q-1) != '\n'; q--, part_len--); - + body = g_strndup (p, part_len + 1); - + g_free (result); d(fprintf (stderr, "*** We got the body ***\n")); - + mesg = g_strdup_printf ("%s\n%s", header, body); g_free (header); g_free (body); d(fprintf (stderr, "*** We got the mesg ***\n")); - + d(fprintf (stderr, "Message:\n%s\n", mesg)); - + msgstream = camel_stream_mem_new_with_buffer (mesg, strlen (mesg) + 1); #if 0 f_stream = camel_stream_filter_new_with_stream (msgstream); @@ -902,7 +902,7 @@ imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex) #endif gtk_object_unref (GTK_OBJECT (msgstream)); /*gtk_object_unref (GTK_OBJECT (f_stream));*/ - + d(fprintf (stderr, "*** We're returning... ***\n")); return msg; diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index cf2de4b304..777dc26e25 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -436,13 +436,21 @@ imap_disconnect (CamelService *service, CamelException *ex) if (!service_class->disconnect (service, ex)) return FALSE; - gtk_object_unref (GTK_OBJECT (store->ostream)); - gtk_object_unref (GTK_OBJECT (store->istream)); - store->ostream = NULL; - store->istream = NULL; + if (store->istream) { + gtk_object_unref (GTK_OBJECT (store->istream)); + store->istream = NULL; + } + + if (store->ostream) { + gtk_object_unref (GTK_OBJECT (store->ostream)); + store->ostream = NULL; + } + g_free (store->dir_sep); store->dir_sep = NULL; + store->current_folder = NULL; + return TRUE; } @@ -609,6 +617,23 @@ get_folder_name (CamelStore *store, const char *folder_name, CamelException *ex) return g_strdup (folder_name); } +static gboolean +stream_is_alive (CamelStream *istream) +{ + CamelStreamFs *fs_stream; + char buf; + + g_return_val_if_fail (istream != NULL, FALSE); + + fs_stream = CAMEL_STREAM_FS (CAMEL_STREAM_BUFFER (istream)->stream); + g_return_val_if_fail (fs_stream->fd != -1, FALSE); + + if (read (fs_stream->fd, (void *) &buf, 0) == 0) + return TRUE; + + return FALSE; +} + static int camel_imap_status (char *cmdid, char *respbuf) { @@ -693,7 +718,6 @@ camel_imap_command (CamelImapStore *store, CamelFolder *folder, char **ret, char va_end (ap); d(fprintf (stderr, "sending : %s %s\r\n", cmdid, cmdbuf)); - fflush (stderr); if (camel_stream_printf (store->ostream, "%s %s\r\n", cmdid, cmdbuf) == -1) { g_free (cmdbuf); @@ -763,32 +787,34 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** { CamelService *service = CAMEL_SERVICE (store); CamelURL *url = service->url; - CamelStreamBuffer *stream = CAMEL_STREAM_BUFFER (store->istream); gint len = 0, recent = 0, status = CAMEL_IMAP_OK; gchar *cmdid, *cmdbuf, *respbuf; GPtrArray *data; va_list app; - + /* First make sure we're connected... */ - if (!service->connected) { + if (!service->connected || !stream_is_alive (store->istream)) { CamelException *ex; - + ex = camel_exception_new (); if (!imap_disconnect (service, ex) || !imap_connect (service, ex)) { camel_exception_free (ex); + + *ret = NULL; + return CAMEL_IMAP_FAIL; } service->connected = TRUE; - + camel_exception_free (ex); } - + if (folder && store->current_folder != folder && strncmp (fmt, "CREATE", 6)) { /* We need to select the correct mailbox first */ char *r, *folder_path, *dir_sep; int s; - + dir_sep = store->dir_sep; if (url && url->path && *(url->path + 1) && strcmp (folder->full_name, "INBOX")) @@ -804,9 +830,9 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** return s; } - + g_free (r); - + store->current_folder = folder; } @@ -815,45 +841,55 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** va_start (app, fmt); cmdbuf = g_strdup_vprintf (fmt, app); va_end (app); - + d(fprintf (stderr, "sending : %s %s\r\n", cmdid, cmdbuf)); - + if (camel_stream_printf (store->ostream, "%s %s\r\n", cmdid, cmdbuf) == -1) { g_free (cmdbuf); g_free (cmdid); - + *ret = g_strdup (strerror (errno)); - + return CAMEL_IMAP_FAIL; } g_free (cmdbuf); - + data = g_ptr_array_new (); - + while (1) { + CamelStreamBuffer *stream = CAMEL_STREAM_BUFFER (store->istream); char *ptr; respbuf = camel_stream_buffer_read_line (stream); if (!respbuf || !strncmp (respbuf, cmdid, strlen (cmdid))) { /* IMAP's last response starts with our command id */ d(fprintf (stderr, "received: %s\n", respbuf ? respbuf : "(null)")); + + if (!respbuf && strcmp (fmt, "LOGOUT")) { + /* we need to force a disconnect here? */ + CamelException *ex; + + ex = camel_exception_new (); + imap_disconnect (service, ex); + camel_exception_free (ex); + } break; } - + d(fprintf (stderr, "received: %s\n", respbuf)); - + g_ptr_array_add (data, respbuf); len += strlen (respbuf) + 1; - + /* If recent was somehow set and this response doesn't begin with a '*' then recent must have been misdetected */ if (recent && *respbuf != '*') recent = 0; - + if (*respbuf == '*' && (ptr = strstr (respbuf, "RECENT"))) { char *rcnt, *ercnt; - d(fprintf (stderr, "*** We may have found a 'RECENT' flag: %s", respbuf)); + d(fprintf (stderr, "*** We may have found a 'RECENT' flag: %s\n", respbuf)); /* Make sure it's in the form: "* %d RECENT" */ rcnt = respbuf + 2; if (*rcnt > '0' || *rcnt < '9') { @@ -863,7 +899,7 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** } } } - + if (respbuf) { g_ptr_array_add (data, respbuf); len += strlen (respbuf) + 1; @@ -873,16 +909,16 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** status = CAMEL_IMAP_FAIL; } g_free (cmdid); - + if (status == CAMEL_IMAP_OK) { char *p; int i; *ret = g_malloc0 (len + 1); - + for (i = 0, p = *ret; i < data->len; i++) { char *ptr, *datap; - + datap = (char *) data->pdata[i]; ptr = (*datap == '.') ? datap + 1 : datap; len = strlen (ptr); @@ -897,9 +933,9 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** else *ret = NULL; } - + g_ptr_array_free (data, TRUE); - + if (folder && recent > 0) gtk_signal_emit_by_name (GTK_OBJECT (folder), "folder_changed", 0); diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h index b38ed769c9..aeabdaa96d 100644 --- a/camel/providers/imap/camel-imap-store.h +++ b/camel/providers/imap/camel-imap-store.h @@ -68,7 +68,7 @@ void camel_imap_store_close (CamelImapStore *store, gboolean expunge, CamelExcep /* support functions */ -enum { CAMEL_IMAP_OK, CAMEL_IMAP_NO, CAMEL_IMAP_BAD, CAMEL_IMAP_FAIL }; +enum { CAMEL_IMAP_OK = 0, CAMEL_IMAP_NO, CAMEL_IMAP_BAD, CAMEL_IMAP_FAIL }; gint camel_imap_command (CamelImapStore *store, CamelFolder *folder, char **ret, char *fmt, ...); gint camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char **ret, char *fmt, ...); -- cgit v1.2.3