From e9dc30dbf0c018bbc845f253bfe0b26baddbeaf2 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 2 Oct 2000 19:08:20 +0000 Subject: Remove camel_folder_{get,free}_subfolder_info, as we want to be able to * camel-folder.[ch]: Remove camel_folder_{get,free}_subfolder_info, as we want to be able to scan the whole subfolder tree without having to open any folders, so this needs to be in CamelStore. Remove can_hold_folders and can_hold_messages flags; things that don't hold messages are no longer considered CamelFolders. * camel-folder-summary.[ch]: Remove CamelFolderInfo stuff. * camel-store.[ch]: Add camel_store_{get,free}_folder_info, as well as camel_store_free_folder_info_full and ..._nop for default implementations, and camel_folder_info_free and camel_folder_info_build as convenience functions. Turn CamelFolderInfo into a tree structure and also add an "url" member. * providers/*/camel-*-folder.c: Remove subfolder_info and can_hold stuff. * providers/*/camel-*-store.c: Add folder_info stuff. * providers/imap/camel-imap-folder.c (imap_summary_free): Free the summary elements with camel_message_info_free, not camel_folder_info_free. Oops. * providers/imap/camel-imap-utils.c: const poison svn path=/trunk/; revision=5663 --- camel/providers/imap/camel-imap-folder.c | 117 +------------------ camel/providers/imap/camel-imap-folder.h | 2 - camel/providers/imap/camel-imap-store.c | 194 +++++++++++++++++++++++++------ camel/providers/imap/camel-imap-utils.c | 10 +- camel/providers/imap/camel-imap-utils.h | 4 +- 5 files changed, 168 insertions(+), 159 deletions(-) (limited to 'camel/providers/imap') diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c index 63ef5b31d1..ab2d7f88b9 100644 --- a/camel/providers/imap/camel-imap-folder.c +++ b/camel/providers/imap/camel-imap-folder.c @@ -79,10 +79,6 @@ static void imap_copy_message_to (CamelFolder *source, const char *uid, static void imap_move_message_to (CamelFolder *source, const char *uid, CamelFolder *destination, CamelException *ex); -/* subfolder listing */ -static GPtrArray *imap_get_subfolder_info_internal (CamelFolder *folder, CamelException *ex); -static GPtrArray *imap_get_subfolder_info (CamelFolder *folder); - /* summary info */ static GPtrArray *imap_get_uids (CamelFolder *folder); static GPtrArray *imap_get_summary_internal (CamelFolder *folder, CamelException *ex); @@ -116,8 +112,6 @@ camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class) camel_folder_class->get_uids = imap_get_uids; camel_folder_class->free_uids = camel_folder_free_nop; - camel_folder_class->get_subfolder_info = imap_get_subfolder_info; - camel_folder_class->free_subfolder_info = camel_folder_free_nop; camel_folder_class->get_message_count = imap_get_message_count; camel_folder_class->get_unread_message_count = imap_get_unread_message_count; @@ -144,14 +138,11 @@ camel_imap_folder_init (gpointer object, gpointer klass) CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); CamelFolder *folder = CAMEL_FOLDER (object); - folder->can_hold_messages = TRUE; - folder->can_hold_folders = TRUE; folder->has_summary_capability = TRUE; folder->has_search_capability = TRUE; imap_folder->summary = NULL; imap_folder->summary_hash = NULL; - imap_folder->lsub = NULL; /* some IMAP daemons support user-flags * * I would not, however, rely on this feature as * @@ -197,9 +188,6 @@ camel_imap_folder_new (CamelStore *parent, const char *folder_name) short_name = folder_name; camel_folder_construct (folder, parent, folder_name, short_name); - if (!*folder_name) - folder->can_hold_messages = FALSE; - return folder; } @@ -211,7 +199,7 @@ imap_summary_free (GPtrArray **summary) if (array) { for (i = 0; i < array->len; i++) - camel_folder_info_free (array->pdata[i]); + camel_message_info_free (array->pdata[i]); g_ptr_array_free (array, TRUE); *summary = NULL; @@ -233,25 +221,14 @@ static void imap_finalize (CamelObject *object) { CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (object); - gint i; - + imap_folder_summary_free (imap_folder); - - if (imap_folder->lsub) { - for (i = 0; i < imap_folder->lsub->len; i++) - camel_folder_info_free (imap_folder->lsub->pdata[i]); - - g_ptr_array_free (imap_folder->lsub, TRUE); - } } static void imap_refresh_info (CamelFolder *folder, CamelException *ex) { - imap_get_subfolder_info_internal (folder, ex); - - if (folder->can_hold_messages) - imap_get_summary_internal (folder, ex); + imap_get_summary_internal (folder, ex); } static void @@ -308,8 +285,6 @@ imap_get_message_count_internal (CamelFolder *folder, CamelException *ex) GPtrArray *response; gint status, count = 0; - g_return_val_if_fail (folder->can_hold_messages, 0); - folder_path = camel_imap_store_folder_path (store, folder->full_name); if (store->has_status_capability) @@ -501,92 +476,6 @@ imap_get_uids (CamelFolder *folder) return array; } -static GPtrArray * -imap_get_subfolder_info_internal (CamelFolder *folder, CamelException *ex) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store); - GPtrArray *response, *listing; - gboolean found_inbox = FALSE; - gint status, i; - gchar *namespace; - CamelFolderInfo *fi; - - g_return_val_if_fail (folder != NULL, g_ptr_array_new ()); - - namespace = camel_imap_store_folder_path (store, folder->full_name); - status = camel_imap_command_extended (store, NULL, &response, ex, - "LIST \"\" \"%s%s*\"", namespace, - *namespace ? store->dir_sep : ""); - - if (status != CAMEL_IMAP_OK) { - g_free (namespace); - - imap_folder->lsub = g_ptr_array_new (); - return imap_folder->lsub; - } - - /* parse out the subfolders */ - listing = g_ptr_array_new (); - if (response) { - for (i = 0; i < response->len; i++) { - gchar *resp, *flags, *sep, *dir; - - resp = response->pdata[i]; - if (!imap_parse_list_response (resp, namespace, &flags, &sep, &dir)) { - g_free (flags); - g_free (sep); - g_free (dir); - continue; - } - - g_free (flags); - - if (*dir) { - d(fprintf (stderr, "adding folder: %s\n", dir)); - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = dir; - fi->name = strrchr (dir, *sep); - if (fi->name) - fi->name = g_strdup (fi->name + 1); - else - fi->name = g_strdup (dir); - /* FIXME: read/unread msg count */ - - if (!g_strcasecmp (dir, "INBOX")) - found_inbox = TRUE; - g_ptr_array_add (listing, fi); - } - - g_free (sep); - } - camel_imap_response_free (response); - } - - if (!*folder->name && !found_inbox) { - fi = g_new0 (CamelFolderInfo, 1); - fi->full_name = g_strdup ("INBOX"); - fi->name = g_strdup ("INBOX"); - /* FIXME: read/unread msg count */ - - g_ptr_array_add (listing, fi); - } - - g_free (namespace); - - imap_folder->lsub = listing; - - return listing; -} - -static GPtrArray * -imap_get_subfolder_info (CamelFolder *folder) -{ - CamelImapFolder *imap_folder = CAMEL_IMAP_FOLDER (folder); - - return imap_folder->lsub; -} - static CamelMimeMessage * imap_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex) { diff --git a/camel/providers/imap/camel-imap-folder.h b/camel/providers/imap/camel-imap-folder.h index d4d960b2a8..41170ce698 100644 --- a/camel/providers/imap/camel-imap-folder.h +++ b/camel/providers/imap/camel-imap-folder.h @@ -48,8 +48,6 @@ typedef struct { GPtrArray *summary; GHashTable *summary_hash; - - GPtrArray *lsub; } CamelImapFolder; diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c index d5fc59b33e..eab33b308f 100644 --- a/camel/providers/imap/camel-imap-store.c +++ b/camel/providers/imap/camel-imap-store.c @@ -60,6 +60,9 @@ static CamelFolder *get_folder (CamelStore *store, const char *folder_name, gboo static char *get_folder_name (CamelStore *store, const char *folder_name, CamelException *ex); static char *get_root_folder_name (CamelStore *store, CamelException *ex); +static CamelFolderInfo *get_folder_info (CamelStore *store, const char *top, + gboolean fast, gboolean recursive, + CamelException *ex); static void imap_keepalive (CamelRemoteStore *store); /*static gboolean stream_is_alive (CamelStream *istream);*/ static int camel_imap_status (char *cmdid, char *respbuf); @@ -87,6 +90,8 @@ camel_imap_store_class_init (CamelImapStoreClass *camel_imap_store_class) camel_store_class->get_folder = get_folder; camel_store_class->get_folder_name = get_folder_name; camel_store_class->get_root_folder_name = get_root_folder_name; + camel_store_class->get_folder_info = get_folder_info; + camel_store_class->free_folder_info = camel_store_free_folder_info_full; camel_remote_store_class->keepalive = imap_keepalive; } @@ -393,33 +398,35 @@ get_folder (CamelStore *store, const char *folder_name, gboolean create, CamelEx CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); CamelFolder *new_folder; char *folder_path; - gboolean exists = FALSE; gboolean selectable; - new_folder = camel_imap_folder_new (store, folder_name); - - /* this is the top-level dir, we already know it exists - it has to! */ - if (!*folder_name) { - camel_folder_refresh_info (new_folder, ex); - return new_folder; - } - folder_path = camel_imap_store_folder_path (imap_store, folder_name); - if (imap_folder_exists (imap_store, folder_path, &selectable, ex)) { - exists = TRUE; - if (!selectable) - new_folder->can_hold_messages = FALSE; - } + if (!imap_folder_exists (imap_store, folder_path, &selectable, ex)) { + if (!create) { + g_free (folder_path); + return NULL; + } - if (!exists && create && !imap_create (imap_store, folder_path, ex)) { + if (!imap_create (imap_store, folder_path, ex)) { + g_free (folder_path); + return NULL; + } + } else if (!selectable) { + camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER, + "%s is not a selectable folder", + folder_name); g_free (folder_path); - camel_object_unref (CAMEL_OBJECT (new_folder)); return NULL; } + g_free (folder_path); - /* this is where we *should refresh_info, not in imap_folder_new() */ + new_folder = camel_imap_folder_new (store, folder_name); camel_folder_refresh_info (new_folder, ex); - + if (camel_exception_is_set (ex)) { + camel_object_unref (CAMEL_OBJECT (new_folder)); + return NULL; + } + return new_folder; } @@ -440,32 +447,145 @@ get_root_folder_name (CamelStore *store, CamelException *ex) return g_strdup (""); } -static void -imap_keepalive (CamelRemoteStore *store) +static CamelFolderInfo * +parse_list_response_as_folder_info (const char *response, + const char *namespace, + const char *base_url) +{ + CamelFolderInfo *fi; + char *flags, *sep, *dir; + + if (!imap_parse_list_response (response, namespace, + &flags, &sep, &dir)) + return NULL; + + fi = g_new0 (CamelFolderInfo, 1); + fi->full_name = dir; + fi->name = strrchr (dir, *sep); + if (fi->name) + fi->name = g_strdup (fi->name + 1); + else + fi->name = g_strdup (dir); + g_free (sep); + if (!e_strstrcase (flags, "\\NoSelect")) + fi->url = g_strdup_printf ("%s%s", base_url, dir); + g_free (flags); + /* FIXME: read/unread msg count */ + + return fi; +} + +static CamelFolderInfo * +get_folder_info (CamelStore *store, const char *top, gboolean fast, + gboolean recursive, CamelException *ex) { CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - - camel_imap_command_extended (imap_store, NULL, NULL, NULL, "NOOP"); + CamelURL *url = CAMEL_SERVICE (store)->url; + gboolean found_inbox = FALSE; + int status, len, i; + GPtrArray *response; + char *dir_sep, *namespace, *base_url, *list; + CamelFolderInfo *topfi, *fi; + + if (!top) + top = ""; + dir_sep = imap_store->dir_sep; + namespace = camel_imap_store_folder_path (imap_store, top); + + /* Yah! I am complicated! */ + base_url = camel_url_to_string (url, FALSE); + len = strlen (base_url); + if (url->path && base_url[len - 1] != *dir_sep) { + base_url = g_realloc (base_url, len + 2); + base_url[len] = *dir_sep; + base_url[len + 1] = '\0'; + } else if (!url->path) { + base_url = g_realloc (base_url, len + 2); + base_url[len] = '/'; + base_url[len + 1] = '\0'; + } + + status = camel_imap_command_extended (imap_store, NULL, &response, ex, + "LIST \"\" \"%s\"", namespace); + if (status != CAMEL_IMAP_OK) { + g_free (namespace); + g_free (base_url); + return NULL; + } + list = camel_imap_response_extract (response, "LIST", ex); + if (!list) { + g_free (namespace); + g_free (base_url); + return NULL; + } + topfi = parse_list_response_as_folder_info (list, namespace, base_url); + g_free (list); + + status = camel_imap_command_extended (imap_store, NULL, &response, ex, + "LIST \"\" \"%s%s%c\"", + namespace, + *namespace ? dir_sep : "", + recursive ? '*' : '%'); + if (status != CAMEL_IMAP_OK) { + g_free (namespace); + g_free (base_url); + return NULL; + } + + /* Turn responses into CamelFolderInfo and remove any + * extraneous responses. + */ + for (i = 0; i < response->len; i++) { + list = response->pdata[i]; + response->pdata[i] = fi = + parse_list_response_as_folder_info (list, namespace, + base_url); + g_free (list); + + if (!response->pdata[i]) { + g_ptr_array_remove_index_fast (response, i--); + continue; + } + + if (!g_strcasecmp (fi->full_name, "INBOX")) + found_inbox = TRUE; + } + + /* Add INBOX, if necessary */ + if (!*top && !found_inbox) { + fi = g_new0 (CamelFolderInfo, 1); + fi->full_name = g_strdup ("INBOX"); + fi->name = g_strdup ("INBOX"); + fi->url = g_strdup_printf ("%sINBOX", base_url); + /* FIXME: read/unread msg count */ + + g_ptr_array_add (response, fi); + } + + /* And assemble */ + camel_folder_info_build (response, topfi, *dir_sep, TRUE); + g_ptr_array_free (response, FALSE); + + /* Remove the top if it's the root of the store. */ + if (!*top && !topfi->sibling) { + fi = topfi; + topfi = topfi->child; + fi->child = NULL; + camel_folder_info_free (fi); + } + + g_free (namespace); + g_free (base_url); + return topfi; } -#if 0 -static gboolean -stream_is_alive (CamelStream *istream) +static void +imap_keepalive (CamelRemoteStore *store) { - 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; + CamelImapStore *imap_store = CAMEL_IMAP_STORE (store); - return FALSE; + camel_imap_command_extended (imap_store, NULL, NULL, NULL, "NOOP"); } -#endif static int camel_imap_status (char *cmdid, char *respbuf) diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c index bb110f1f90..4658341e6a 100644 --- a/camel/providers/imap/camel-imap-utils.c +++ b/camel/providers/imap/camel-imap-utils.c @@ -33,12 +33,12 @@ #define d(x) x char * -imap_next_word (char *buf) +imap_next_word (const char *buf) { char *word; /* skip over current word */ - for (word = buf; *word && *word != ' '; word++); + for (word = (char *)buf; *word && *word != ' '; word++); /* skip over white space */ for ( ; *word && *word == ' '; word++); @@ -47,7 +47,7 @@ imap_next_word (char *buf) } gboolean -imap_parse_list_response (char *buf, char *namespace, char **flags, char **sep, char **folder) +imap_parse_list_response (const char *buf, const char *namespace, char **flags, char **sep, char **folder) { char *word, *ep, *f; @@ -96,7 +96,9 @@ imap_parse_list_response (char *buf, char *namespace, char **flags, char **sep, /* chop out the folder prefix */ if (*namespace && !strncmp (*folder, namespace, strlen (namespace))) { - f = *folder + strlen (namespace) + strlen (*sep); + f = *folder + strlen (namespace); + if (!strncmp (f, *sep, strlen (*sep))) + f += strlen (*sep); memmove (*folder, f, strlen (f) + 1); } diff --git a/camel/providers/imap/camel-imap-utils.h b/camel/providers/imap/camel-imap-utils.h index 6f450fc8e8..b08c179926 100644 --- a/camel/providers/imap/camel-imap-utils.h +++ b/camel/providers/imap/camel-imap-utils.h @@ -30,9 +30,9 @@ extern "C" { #include -char *imap_next_word (char *buf); +char *imap_next_word (const char *buf); -gboolean imap_parse_list_response (char *buf, char *namespace, char **flags, char **sep, char **folder); +gboolean imap_parse_list_response (const char *buf, const char *namespace, char **flags, char **sep, char **folder); char *imap_translate_sexp (const char *expression); -- cgit v1.2.3