From b4fa8e15a8014442a0a21cc121cedda16cdc272a Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Mon, 24 Jul 2000 23:10:21 +0000 Subject: Initialize the summary and subfolder listing. (imap_summary_free): Now 2000-07-24 Jeffrey Stedfast * providers/imap/camel-imap-folder.c (camel_imap_folder_new): Initialize the summary and subfolder listing. (imap_summary_free): Now takes a GPtrArray arg rather than a CamelImapFolder as it increases it's usefullness for free()'ing temporary summaries. (imap_get_message_count_internal): A new convenience function for getting the actual message count on a server to be used by imap_get_summary_internal) (imap_get_message_count): Since the Camel API is on the move again, the future version of this function will not be able to make a call to the store, it must only access previously fetched data (thus the creation of the _internal function) (imap_get_subfolder_names_internal): Again, because the future version of imap_get_subfolder_names will not take an exception, we must rename this function which will be called by camel_imap_folder_new() (imap_get_subfolder_names): We now return the previously collected subfolder listing that the _internal function fetched previously (imap_get_summary_internal): Again, same idea as the previous _internal functions... (imap_get_summary): Again... now returns a previously aquired summary * providers/imap/camel-imap-store.c (imap_noop): This will hopefully prevent the imap store from disconnecting. (imap_connect): Modified to add a gtk timeout event that will call imap_noop() every 10 minutes (we may want to change this time value) (imap_disconnect): Modified to remove the NOOP timeout event from the store. (camel_imap_command_extended): Commented out the code that would try and detect if the store was disconnected and then reconnect if it was needed. svn path=/trunk/; revision=4298 --- camel/ChangeLog | 33 +++++ camel/providers/imap/camel-imap-folder.c | 220 +++++++++++++++++-------------- camel/providers/imap/camel-imap-folder.h | 2 +- camel/providers/imap/camel-imap-store.c | 40 +++++- camel/providers/imap/camel-imap-store.h | 2 + 5 files changed, 194 insertions(+), 103 deletions(-) (limited to 'camel') diff --git a/camel/ChangeLog b/camel/ChangeLog index 9e87b1ece4..fffa73f980 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,36 @@ +2000-07-24 Jeffrey Stedfast + + * providers/imap/camel-imap-folder.c (camel_imap_folder_new): + Initialize the summary and subfolder listing. + (imap_summary_free): Now takes a GPtrArray arg rather than a + CamelImapFolder as it increases it's usefullness for free()'ing + temporary summaries. + (imap_get_message_count_internal): A new convenience function for + getting the actual message count on a server to be used by + imap_get_summary_internal) + (imap_get_message_count): Since the Camel API is on the move again, + the future version of this function will not be able to make a + call to the store, it must only access previously fetched data (thus + the creation of the _internal function) + (imap_get_subfolder_names_internal): Again, because the future version + of imap_get_subfolder_names will not take an exception, we must rename + this function which will be called by camel_imap_folder_new() + (imap_get_subfolder_names): We now return the previously collected + subfolder listing that the _internal function fetched previously + (imap_get_summary_internal): Again, same idea as the previous _internal + functions... + (imap_get_summary): Again... now returns a previously aquired summary + + * providers/imap/camel-imap-store.c (imap_noop): This will hopefully + prevent the imap store from disconnecting. + (imap_connect): Modified to add a gtk timeout event that will call + imap_noop() every 10 minutes (we may want to change this time value) + (imap_disconnect): Modified to remove the NOOP timeout event from the + store. + (camel_imap_command_extended): Commented out the code that would try + and detect if the store was disconnected and then reconnect if it was + needed. + 2000-07-24 Dan Winship * camel-folder.[ch]: Remove camel_folder_get_message_uid, which diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c index 1093005376..cd5c8484c2 100644 --- a/camel/providers/imap/camel-imap-folder.c +++ b/camel/providers/imap/camel-imap-folder.c @@ -63,26 +63,31 @@ static void imap_init (CamelFolder *folder, CamelStore *parent_store, gchar *separator, gboolean path_begns_with_sep, CamelException *ex); +static void imap_finalize (GtkObject *object); + static void imap_sync (CamelFolder *folder, gboolean expunge, CamelException *ex); static void imap_expunge (CamelFolder *folder, CamelException *ex); + +static gint imap_get_message_count_internal (CamelFolder *folder, CamelException *ex); static gint imap_get_message_count (CamelFolder *folder, CamelException *ex); static gint imap_get_unread_message_count (CamelFolder *folder, CamelException *ex); + +static CamelMimeMessage *imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex); static void imap_append_message (CamelFolder *folder, CamelMimeMessage *message, guint32 flags, CamelException *ex); static void imap_copy_message_to (CamelFolder *source, const char *uid, CamelFolder *destination, CamelException *ex); static void imap_move_message_to (CamelFolder *source, const char *uid, CamelFolder *destination, CamelException *ex); -static GPtrArray *imap_get_uids (CamelFolder *folder, CamelException *ex); +static void imap_delete_message (CamelFolder *folder, const gchar *uid, CamelException *ex); + static gboolean imap_parse_subfolder_line (gchar *buf, gchar *namespace, gchar **flags, gchar **sep, gchar **folder); +static GPtrArray *imap_get_subfolder_names_internal (CamelFolder *folder, CamelException *ex); static GPtrArray *imap_get_subfolder_names (CamelFolder *folder, CamelException *ex); + +static GPtrArray *imap_get_uids (CamelFolder *folder, CamelException *ex); +static GPtrArray *imap_get_summary_internal (CamelFolder *folder, CamelException *ex); static GPtrArray *imap_get_summary (CamelFolder *folder, CamelException *ex); static const CamelMessageInfo *imap_get_message_info (CamelFolder *folder, const char *uid); -static void imap_set_message_user_flag (CamelFolder *folder, const char *uid, const char *name, - gboolean value, CamelException *ex); -static gboolean imap_get_message_user_flag (CamelFolder *folder, const char *uid, const char *name, CamelException *ex); -static CamelMimeMessage *imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex); -static void imap_delete_message (CamelFolder *folder, const gchar *uid, CamelException *ex); -static GPtrArray *imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex); -static void imap_finalize (GtkObject *object); +static GPtrArray *imap_search_by_expression (CamelFolder *folder, const char *expression, CamelException *ex); /* flag methods */ static guint32 imap_get_permanent_flags (CamelFolder *folder, CamelException *ex); @@ -94,6 +99,7 @@ static gboolean imap_get_message_user_flag (CamelFolder *folder, const char *uid static void imap_set_message_user_flag (CamelFolder *folder, const char *uid, const char *name, gboolean value, CamelException *ex); + static void camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class) { @@ -146,10 +152,10 @@ camel_imap_folder_init (gpointer object, gpointer klass) folder->can_hold_messages = TRUE; folder->can_hold_folders = TRUE; folder->has_summary_capability = TRUE; - folder->has_search_capability = FALSE; /* default - we have to query IMAP to know for sure */ + folder->has_search_capability = FALSE; /* this gets set in imap_init */ imap_folder->summary = NULL; - imap_folder->count = -1; + imap_folder->lsub = NULL; } GtkType @@ -186,19 +192,22 @@ camel_imap_folder_new (CamelStore *parent, char *folder_name, CamelException *ex CF_CLASS (folder)->init (folder, parent, NULL, folder_name, dir_sep, FALSE, ex); + imap_get_subfolder_names_internal (folder, ex); + imap_get_summary_internal (folder, ex); + return folder; } static void -imap_summary_free (CamelImapFolder *imap_folder) +imap_summary_free (GPtrArray *summary) { CamelMessageInfo *info; gint i, max; - - if (imap_folder->summary != NULL) { - max = imap_folder->summary->len; + + if (summary) { + max = summary->len; for (i = 0; i < max; i++) { - info = g_ptr_array_index (imap_folder->summary, i); + info = g_ptr_array_index (summary, i); g_free (info->subject); g_free (info->from); g_free (info->to); @@ -210,20 +219,30 @@ imap_summary_free (CamelImapFolder *imap_folder) info = NULL; } - g_ptr_array_free (imap_folder->summary, TRUE); - imap_folder->summary = NULL; + g_ptr_array_free (summary, TRUE); + summary = NULL; } - - imap_folder->count = -1; } static void imap_finalize (GtkObject *object) { - /* TODO: do we need to do more here? */ + /* TODO: do we need to do more cleanup here? */ CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); + gint max, i; + + imap_summary_free (imap_folder->summary); - imap_summary_free (imap_folder); + if (imap_folder->lsub) { + max = imap_folder->lsub->len; + + for (i = 0; i < max; i++) { + g_free (imap_folder->lsub->pdata[i]); + imap_folder->lsub->pdata[i] = NULL; + } + + g_ptr_array_free (imap_folder->lsub, TRUE); + } } static void @@ -372,25 +391,20 @@ imap_expunge (CamelFolder *folder, CamelException *ex) g_free (result); - imap_summary_free (imap_folder); + imap_summary_free (imap_folder->summary); gtk_signal_emit_by_name (GTK_OBJECT (folder), "folder_changed", 0); } static gint -imap_get_message_count (CamelFolder *folder, CamelException *ex) +imap_get_message_count_internal (CamelFolder *folder, CamelException *ex) { - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); CamelStore *store = CAMEL_STORE (folder->parent_store); CamelURL *url = CAMEL_SERVICE (store)->url; gchar *result, *msg_count, *folder_path, *dir_sep; - gint status; - - g_return_val_if_fail (folder != NULL, -1); + gint status, count = 0; - /* If we already have a count, return */ - if (imap_folder->count != -1) - return imap_folder->count; + g_return_val_if_fail (folder != NULL, 0); dir_sep = CAMEL_IMAP_STORE (folder->parent_store)->dir_sep; @@ -411,7 +425,7 @@ imap_get_message_count (CamelFolder *folder, CamelException *ex) "Unknown error"); g_free (result); g_free (folder_path); - return -1; + return 0; } g_free (folder_path); @@ -423,12 +437,23 @@ imap_get_message_count (CamelFolder *folder, CamelException *ex) for ( ; *msg_count == ' '; msg_count++); /* we should now be pointing to the message count */ - imap_folder->count = atoi (msg_count); + count = atoi (msg_count); } } g_free (result); - return imap_folder->count; + return count; +} + +static gint +imap_get_message_count (CamelFolder *folder, CamelException *ex) +{ + CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + + if (imap_folder->summary) + return imap_folder->summary->len; + else + return 0; } static gint @@ -439,11 +464,11 @@ imap_get_unread_message_count (CamelFolder *folder, CamelException *ex) GPtrArray *infolist; gint i, count = 0; - g_return_val_if_fail (folder != NULL, -1); + g_return_val_if_fail (folder != NULL, 0); /* If we don't have a message count, return */ - if (imap_folder->count == -1) - return -1; + if (!imap_folder->summary) + return 0; infolist = imap_get_summary (folder, ex); @@ -616,18 +641,18 @@ imap_get_uids (CamelFolder *folder, CamelException *ex) CamelMessageInfo *info; GPtrArray *array, *infolist; gint i, count; - + infolist = imap_get_summary (folder, ex); count = infolist->len; array = g_ptr_array_new (); g_ptr_array_set_size (array, count); - + for (i = 0; i < count; i++) { info = (CamelMessageInfo *) g_ptr_array_index (infolist, i); array->pdata[i] = g_strdup (info->uid); } - + return array; } @@ -635,14 +660,14 @@ static gboolean imap_parse_subfolder_line (gchar *buf, gchar *namespace, gchar **flags, gchar **sep, gchar **folder) { gchar *ptr, *eptr, *f; - + *flags = NULL; *sep = NULL; *folder = NULL; - + if (g_strncasecmp (buf, "* LIST", 6)) return FALSE; - + ptr = strstr (buf + 6, "("); if (!ptr) return FALSE; @@ -653,22 +678,22 @@ imap_parse_subfolder_line (gchar *buf, gchar *namespace, gchar **flags, gchar ** return FALSE; *flags = g_strndup (ptr, (gint)(eptr - ptr)); - + ptr = strstr (eptr, "\""); if (!ptr) return FALSE; - + ptr++; eptr = strstr (ptr, "\""); if (!eptr) return FALSE; - + *sep = g_strndup (ptr, (gint)(eptr - ptr)); - + ptr = eptr + 1; *folder = g_strdup (ptr); g_strstrip (*folder); - + /* chop out the folder prefix */ if (*namespace && !strncmp (*folder, namespace, strlen (namespace))) { f = *folder + strlen (namespace) + strlen (*sep); @@ -676,12 +701,12 @@ imap_parse_subfolder_line (gchar *buf, gchar *namespace, gchar **flags, gchar ** } string_unquote (*folder); /* unquote the mailbox if it's quoted */ - + return TRUE; } static GPtrArray * -imap_get_subfolder_names (CamelFolder *folder, CamelException *ex) +imap_get_subfolder_names_internal (CamelFolder *folder, CamelException *ex) { CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); CamelStore *store = CAMEL_STORE (folder->parent_store); @@ -689,14 +714,11 @@ imap_get_subfolder_names (CamelFolder *folder, CamelException *ex) GPtrArray *listing; gint status; gchar *result, *namespace, *dir_sep; - + g_return_val_if_fail (folder != NULL, g_ptr_array_new ()); - if (imap_folder->count != -1) - return g_ptr_array_new (); - dir_sep = CAMEL_IMAP_STORE (folder->parent_store)->dir_sep; - + if (url && url->path) { if (!strcmp (folder->full_name, "INBOX")) namespace = g_strdup (url->path + 1); @@ -719,7 +741,9 @@ imap_get_subfolder_names (CamelFolder *folder, CamelException *ex) "Unknown error"); g_free (result); g_free (namespace); - return g_ptr_array_new (); + + imap_folder->lsub = g_ptr_array_new (); + return imap_folder->lsub; } /* parse out the subfolders */ @@ -742,18 +766,18 @@ imap_get_subfolder_names (CamelFolder *folder, CamelException *ex) g_free (flags); g_free (sep); g_free (folder); - + if (*ptr == '\n') ptr++; continue; } g_free (flags); - + d(fprintf (stderr, "adding folder: %s\n", folder)); g_ptr_array_add (listing, folder); - + g_free (sep); if (*ptr == '\n') @@ -763,14 +787,24 @@ imap_get_subfolder_names (CamelFolder *folder, CamelException *ex) g_free (result); g_free (namespace); + imap_folder->lsub = listing; + return listing; } +static GPtrArray * +imap_get_subfolder_names (CamelFolder *folder, CamelException *ex) +{ + CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + + return imap_folder->lsub; +} + static void imap_delete_message (CamelFolder *folder, const gchar *uid, CamelException *ex) { CamelMessageInfo *info; - + if (!(info = (CamelMessageInfo *)imap_get_message_info (folder, uid))) { CamelService *service = CAMEL_SERVICE (folder->parent_store); @@ -779,7 +813,7 @@ imap_delete_message (CamelFolder *folder, const gchar *uid, CamelException *ex) uid, service->url->host, "Unknown error"); return; } - + imap_set_message_flags (folder, uid, CAMEL_MESSAGE_DELETED, ~(info->flags), ex); } @@ -984,54 +1018,28 @@ get_header_field (gchar *header, gchar *field) static char *header_fields[] = { "subject", "from", "to", "cc", "date", "received", "message-id", "references", "in-reply-to", "" }; -/* - a2 FETCH 1:3 (UID FLAGS BODY[HEADER.FIELDS (FROM SUBJECT)]) - * 1 FETCH (UID 1469 FLAGS (\Seen) BODY[HEADER.FIELDS ("FROM" "SUBJECT")] {87} - From: Joakim Ziegler - Subject: Helix CVS: webroot joakim - - ) - * 2 FETCH (UID 1470 FLAGS (\Seen) BODY[HEADER.FIELDS ("FROM" "SUBJECT")] {87} - From: Joakim Ziegler - Subject: Helix CVS: webroot joakim - - ) - * 3 FETCH (UID 1471 FLAGS (\Seen) BODY[HEADER.FIELDS ("FROM" "SUBJECT")] {87} - From: Joakim Ziegler - Subject: Re: [HC All-hands] helix news - - ) - a2 OK FETCH completed - */ static GPtrArray * -imap_get_summary (CamelFolder *folder, CamelException *ex) +imap_get_summary_internal (CamelFolder *folder, CamelException *ex) { + /* This ALWAYS updates the summary except on fail */ CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); GPtrArray *summary = NULL, *headers = NULL; gint num, i, j, status = 0; char *result, *q, *node; const char *received; struct _header_raw *h, *tail = NULL; - - /*if (imap_folder->summary) - return imap_folder->summary;*/ - num = imap_get_message_count (folder, ex); - - if (imap_folder->summary && imap_folder->summary->len == num) - return imap_folder->summary; - - /* clean up any previous summary data */ - imap_summary_free (imap_folder); - - summary = g_ptr_array_new (); + num = imap_get_message_count_internal (folder, ex); switch (num) { case 0: - imap_folder->summary = summary; + /* clean up any previous summary data */ + imap_summary_free (imap_folder->summary); - return summary; + imap_folder->summary = g_ptr_array_new (); + + return imap_folder->summary; case 1: status = camel_imap_command_extended (CAMEL_IMAP_STORE (folder->parent_store), folder, &result, "FETCH 1 (UID FLAGS BODY[HEADER.FIELDS " @@ -1055,11 +1063,14 @@ imap_get_summary (CamelFolder *folder, CamelException *ex) "Unknown error"); g_free (result); - imap_folder->summary = summary; + g_ptr_array_free (summary, TRUE); - return summary; + return imap_folder->summary; } + /* initialize our new summary-to-be */ + summary = g_ptr_array_new (); + /* create our array of headers from the server response */ headers = g_ptr_array_new (); node = result; @@ -1108,7 +1119,7 @@ imap_get_summary (CamelFolder *folder, CamelException *ex) } for (flags += 6; *flags && *flags != '('; flags++); /* advance to */ - for (q = flags; *q && *q != ')' /*&& *q != ' '*/; q++); /* find the end of */ + for (q = flags; *q && *q != ')'; q++); /* find the end of */ flags = g_strndup (flags, (gint)(q - flags + 1)); d(fprintf (stderr, "*** info->flags = %s\n", flags)); @@ -1191,9 +1202,20 @@ imap_get_summary (CamelFolder *folder, CamelException *ex) g_ptr_array_free (headers, TRUE); + /* clean up any previous summary data */ + imap_summary_free (imap_folder->summary); + imap_folder->summary = summary; - return summary; + return imap_folder->summary; +} + +static GPtrArray * +imap_get_summary (CamelFolder *folder, CamelException *ex) +{ + CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); + + return imap_folder->summary; } /* get a single message info, by uid */ @@ -1226,7 +1248,7 @@ imap_get_message_info (CamelFolder *folder, const char *uid) ex = camel_exception_new (); - if (!imap_get_summary (folder, ex)) { + if (!imap_get_summary_internal (folder, ex)) { camel_exception_free (ex); return NULL; } diff --git a/camel/providers/imap/camel-imap-folder.h b/camel/providers/imap/camel-imap-folder.h index 17f6d505d2..ba2d1daa70 100644 --- a/camel/providers/imap/camel-imap-folder.h +++ b/camel/providers/imap/camel-imap-folder.h @@ -47,7 +47,7 @@ typedef struct { CamelFolderSearch *search; /* used to run searches */ GPtrArray *summary; - gint count; + GPtrArray *lsub; } CamelImapFolder; diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index 777dc26e25..2554588461 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -65,6 +65,8 @@ static char *get_name (CamelService *service, gboolean brief); static CamelFolder *get_folder (CamelStore *store, const char *folder_name, gboolean create, CamelException *ex); static char *get_folder_name (CamelStore *store, const char *folder_name, CamelException *ex); +static gboolean imap_noop (gpointer data); +static gboolean stream_is_alive (CamelStream *istream); static int camel_imap_status (char *cmdid, char *respbuf); static void @@ -105,6 +107,8 @@ camel_imap_store_init (gpointer object, gpointer klass) store->folders = g_hash_table_new (g_str_hash, g_str_equal); CAMEL_IMAP_STORE (store)->dir_sep = NULL; + CAMEL_IMAP_STORE (store)->current_folder = NULL; + CAMEL_IMAP_STORE (store)->timeout_id = 0; } GtkType @@ -270,7 +274,12 @@ imap_connect (CamelService *service, CamelException *ex) gchar *buf, *msg, *result, *errbuf = NULL; gboolean authenticated = FALSE; - + /* FIXME: do we really need this here? */ + if (store->timeout_id) { + gtk_timeout_remove (store->timeout_id); + store->timeout_id = 0; + } + h = camel_service_gethost (service, ex); if (!h) return FALSE; @@ -412,6 +421,9 @@ imap_connect (CamelService *service, CamelException *ex) } } } + + /* Lets add a timeout so that we can hopefully prevent getting disconnected */ + store->timeout_id = gtk_timeout_add (60000, imap_noop, store); return TRUE; } @@ -450,6 +462,11 @@ imap_disconnect (CamelService *service, CamelException *ex) store->dir_sep = NULL; store->current_folder = NULL; + + if (store->timeout_id) { + gtk_timeout_remove (store->timeout_id); + store->timeout_id = 0; + } return TRUE; } @@ -617,6 +634,20 @@ get_folder_name (CamelStore *store, const char *folder_name, CamelException *ex) return g_strdup (folder_name); } +static gboolean +imap_noop (gpointer data) +{ + CamelImapStore *store = CAMEL_IMAP_STORE (data); + char *result; + int status; + + status = camel_imap_command_extended (store, store->current_folder, &result, "NOOP"); + + g_free (result); + + return TRUE; +} + static gboolean stream_is_alive (CamelStream *istream) { @@ -791,7 +822,8 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** gchar *cmdid, *cmdbuf, *respbuf; GPtrArray *data; va_list app; - + +#if 0 /* First make sure we're connected... */ if (!service->connected || !stream_is_alive (store->istream)) { CamelException *ex; @@ -809,6 +841,7 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** camel_exception_free (ex); } +#endif if (folder && store->current_folder != folder && strncmp (fmt, "CREATE", 6)) { /* We need to select the correct mailbox first */ @@ -864,7 +897,7 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** 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 0 if (!respbuf && strcmp (fmt, "LOGOUT")) { /* we need to force a disconnect here? */ CamelException *ex; @@ -873,6 +906,7 @@ camel_imap_command_extended (CamelImapStore *store, CamelFolder *folder, char ** imap_disconnect (service, ex); camel_exception_free (ex); } +#endif break; } diff --git a/camel/providers/imap/camel-imap-store.h b/camel/providers/imap/camel-imap-store.h index aeabdaa96d..e1bdc86a9c 100644 --- a/camel/providers/imap/camel-imap-store.h +++ b/camel/providers/imap/camel-imap-store.h @@ -52,6 +52,8 @@ typedef struct { gboolean has_search_capability; gchar *dir_sep; + + guint timeout_id; } CamelImapStore; -- cgit v1.2.3