From ab880a9066b4f32d08ba99903d09a4a5675dd214 Mon Sep 17 00:00:00 2001 From: hiro Date: Fri, 14 Sep 2007 08:12:20 +0000 Subject: modified the method of getting IMAP4 folder list. git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@1900 ee746299-78ed-0310-b773-934348b2243d --- ChangeLog | 7 +++ ChangeLog.ja | 8 ++++ libsylph/folder.c | 41 ++++++++++++++++ libsylph/folder.h | 1 + libsylph/imap.c | 139 ++++++++++++++++++++++++++++++++++++++---------------- 5 files changed, 156 insertions(+), 40 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0e29d6f8..c2e5eec8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2007-09-14 + + * libsylph/folder.[ch]: folder_item_copy(): new. It duplicates + FolderItem struct. + * libsylph/imap.c: imap_scan_tree(): use 'LIST "" "*"' command + instead of 'LIST "" "%"' to obtain folder list. + 2007-09-14 * src/inc.[ch] diff --git a/ChangeLog.ja b/ChangeLog.ja index e66cf840..9045ea9f 100644 --- a/ChangeLog.ja +++ b/ChangeLog.ja @@ -1,3 +1,11 @@ +2007-09-14 + + * libsylph/folder.[ch]: folder_item_copy(): 新規。 FolderItem 構造体 + を複製する。 + * libsylph/imap.c: imap_scan_tree(): フォルダリストを取得するとき + 'LIST "" "%"' コマンドの代わりに 'LIST "" "*"' コマンドを使用する + ようにした。 + 2007-09-14 * src/inc.[ch] diff --git a/libsylph/folder.c b/libsylph/folder.c index 0649ca21..cb630521 100644 --- a/libsylph/folder.c +++ b/libsylph/folder.c @@ -209,6 +209,47 @@ void folder_item_append(FolderItem *parent, FolderItem *item) item->node = g_node_append_data(parent->node, item); } +FolderItem *folder_item_copy(FolderItem *item) +{ + FolderItem *new_item; + + new_item = g_new0(FolderItem, 1); + + new_item->stype = item->stype; + new_item->name = g_strdup(item->name); + new_item->path = g_strdup(item->path); + new_item->mtime = item->mtime; + new_item->new = item->new; + new_item->unread = item->unread; + new_item->total = item->total; + new_item->unmarked_num = item->unmarked_num; + new_item->last_num = item->last_num; + new_item->no_sub = item->no_sub; + new_item->no_select = item->no_select; + new_item->collapsed = item->collapsed; + new_item->threaded = item->threaded; + new_item->opened = item->opened; + new_item->updated = item->updated; + new_item->cache_dirty = item->cache_dirty; + new_item->mark_dirty = item->mark_dirty; + new_item->node = item->node; + new_item->parent = item->parent; + new_item->folder = item->folder; + new_item->account = item->account; + new_item->ac_apply_sub = item->ac_apply_sub; + new_item->auto_to = g_strdup(item->auto_to); + new_item->use_auto_to_on_reply = item->use_auto_to_on_reply; + new_item->auto_cc = g_strdup(item->auto_cc); + new_item->auto_bcc = g_strdup(item->auto_bcc); + new_item->auto_replyto = g_strdup(item->auto_replyto); + new_item->mark_queue = item->mark_queue; + new_item->last_selected = item->last_selected; + new_item->qsearch_cond_type = item->qsearch_cond_type; + new_item->data = item->data; + + return new_item; +} + static gboolean folder_item_remove_func(GNode *node, gpointer data) { FolderItem *item = FOLDER_ITEM(node->data); diff --git a/libsylph/folder.h b/libsylph/folder.h index 3d2e577b..db9c3bf9 100644 --- a/libsylph/folder.h +++ b/libsylph/folder.h @@ -325,6 +325,7 @@ FolderItem *folder_item_new (const gchar *name, const gchar *path); void folder_item_append (FolderItem *parent, FolderItem *item); +FolderItem *folder_item_copy (FolderItem *item); void folder_item_remove (FolderItem *item); void folder_item_remove_children (FolderItem *item); void folder_item_destroy (FolderItem *item); diff --git a/libsylph/imap.c b/libsylph/imap.c index bcac6355..35c053e7 100644 --- a/libsylph/imap.c +++ b/libsylph/imap.c @@ -176,10 +176,15 @@ static gint imap_auth (IMAPSession *session, IMAPAuthType type); static gint imap_scan_tree_recursive (IMAPSession *session, + FolderItem *item, + GSList *item_list); +static GSList *imap_get_folder_list (IMAPSession *session, FolderItem *item); static GSList *imap_parse_list (IMAPSession *session, const gchar *real_path, gchar *separator); +static GSList *imap_get_part_folder_list(GSList *item_list, + FolderItem *item); static void imap_create_missing_folders (Folder *folder); static FolderItem *imap_create_special_folder @@ -1702,6 +1707,7 @@ static gint imap_scan_tree(Folder *folder) FolderItem *item = NULL; IMAPSession *session; gchar *root_folder = NULL; + GSList *item_list, *cur; g_return_val_if_fail(folder != NULL, -1); g_return_val_if_fail(folder->account != NULL, -1); @@ -1757,56 +1763,33 @@ static gint imap_scan_tree(Folder *folder) folder->node = item->node = g_node_new(item); } - imap_scan_tree_recursive(session, FOLDER_ITEM(folder->node->data)); + item_list = imap_get_folder_list(session, item); + imap_scan_tree_recursive(session, item, item_list); imap_create_missing_folders(folder); + for (cur = item_list; cur != NULL; cur = cur->next) + folder_item_destroy(FOLDER_ITEM(cur->data)); + g_slist_free(item_list); + return 0; } -static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item) +static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item, + GSList *item_list) { Folder *folder; IMAPFolder *imapfolder; FolderItem *new_item; - GSList *item_list, *cur; + GSList *part_list, *cur; GNode *node; - gchar *real_path; - gchar *wildcard_path; - gchar separator; - gchar wildcard[3]; g_return_val_if_fail(item != NULL, -1); g_return_val_if_fail(item->folder != NULL, -1); g_return_val_if_fail(item->no_sub == FALSE, -1); folder = item->folder; - imapfolder = IMAP_FOLDER(folder); - - separator = imap_get_path_separator(imapfolder, item->path); - if (folder->ui_func) - folder->ui_func(folder, item, folder->ui_func_data); - - if (item->path) { - wildcard[0] = separator; - wildcard[1] = '%'; - wildcard[2] = '\0'; - real_path = imap_get_real_path(imapfolder, item->path); - } else { - wildcard[0] = '%'; - wildcard[1] = '\0'; - real_path = g_strdup(""); - } - - Xstrcat_a(wildcard_path, real_path, wildcard, - {g_free(real_path); return IMAP_ERROR;}); - QUOTE_IF_REQUIRED(wildcard_path, wildcard_path); - - imap_cmd_gen_send(session, "LIST \"\" %s", wildcard_path); - - strtailchomp(real_path, separator); - item_list = imap_parse_list(session, real_path, NULL); - g_free(real_path); + part_list = imap_get_part_folder_list(item_list, item); node = item->node->children; while (node != NULL) { @@ -1815,7 +1798,7 @@ static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item) new_item = NULL; - for (cur = item_list; cur != NULL; cur = cur->next) { + for (cur = part_list; cur != NULL; cur = cur->next) { FolderItem *cur_item = FOLDER_ITEM(cur->data); if (!strcmp2(old_item->path, cur_item->path)) { new_item = cur_item; @@ -1848,7 +1831,7 @@ static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item) node = next; } - for (cur = item_list; cur != NULL; cur = cur->next) { + for (cur = part_list; cur != NULL; cur = cur->next) { FolderItem *cur_item = FOLDER_ITEM(cur->data); new_item = NULL; for (node = item->node->children; node != NULL; @@ -1856,13 +1839,12 @@ static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item) if (!strcmp2(FOLDER_ITEM(node->data)->path, cur_item->path)) { new_item = FOLDER_ITEM(node->data); - folder_item_destroy(cur_item); cur_item = NULL; break; } } if (!new_item) { - new_item = cur_item; + new_item = folder_item_copy(cur_item); debug_print("new folder '%s' found.\n", new_item->path); folder_item_append(item, new_item); } @@ -1899,14 +1881,50 @@ static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item) imap_scan_folder(folder, new_item); #endif if (new_item->no_sub == FALSE) - imap_scan_tree_recursive(session, new_item); + imap_scan_tree_recursive(session, new_item, item_list); } - g_slist_free(item_list); + g_slist_free(part_list); return IMAP_SUCCESS; } +static GSList *imap_get_folder_list(IMAPSession *session, FolderItem *item) +{ + Folder *folder; + IMAPFolder *imapfolder; + gchar *real_path; + gchar *wildcard_path; + gchar separator; + gchar wildcard[3]; + GSList *item_list; + + folder = item->folder; + imapfolder = IMAP_FOLDER(folder); + + separator = imap_get_path_separator(imapfolder, item->path); + + if (folder->ui_func) + folder->ui_func(folder, item, folder->ui_func_data); + + if (item->path) { + real_path = imap_get_real_path(imapfolder, item->path); + strtailchomp(real_path, separator); + wildcard_path = g_strdup_printf("%s%c*", real_path, separator); + } else { + real_path = g_strdup(""); + wildcard_path = g_strdup("*"); + } + + imap_cmd_gen_send(session, "LIST \"\" \"%s\"", wildcard_path); + + item_list = imap_parse_list(session, real_path, NULL); + g_free(real_path); + g_free(wildcard_path); + + return item_list; +} + static GSList *imap_parse_list(IMAPSession *session, const gchar *real_path, gchar *separator) { @@ -1984,7 +2002,7 @@ static GSList *imap_parse_list(IMAPSession *session, const gchar *real_path, strcasestr(flags, "\\Noselect") != NULL) new_item->no_select = TRUE; - item_list = g_slist_append(item_list, new_item); + item_list = g_slist_prepend(item_list, new_item); debug_print("folder '%s' found.\n", loc_path); g_free(loc_path); @@ -1993,9 +2011,50 @@ static GSList *imap_parse_list(IMAPSession *session, const gchar *real_path, g_string_free(str, TRUE); + item_list = g_slist_reverse(item_list); return item_list; } +static GSList *imap_get_part_folder_list(GSList *item_list, FolderItem *item) +{ + FolderItem *cur_item; + GSList *part_list = NULL, *cur; + gint len; + + if (!item->path) { + debug_print("imap_get_part_folder_list(): get root folders\n"); + for (cur = item_list; cur != NULL; cur = cur->next) { + cur_item = FOLDER_ITEM(cur->data); + + if (!strchr(cur_item->path, '/')) { + part_list = g_slist_prepend(part_list, + cur_item); + debug_print("append '%s'\n", cur_item->path); + } + } + part_list = g_slist_reverse(part_list); + return part_list; + } + + len = strlen(item->path); + debug_print("imap_get_part_folder_list(): get folders under '%s'\n", + item->path); + + for (cur = item_list; cur != NULL; cur = cur->next) { + cur_item = FOLDER_ITEM(cur->data); + + if (!strncmp(cur_item->path, item->path, len) && + cur_item->path[len] == '/' && + !strchr(cur_item->path + len + 1, '/')) { + part_list = g_slist_prepend(part_list, cur_item); + debug_print("append '%s'\n", cur_item->path); + } + } + + part_list = g_slist_reverse(part_list); + return part_list; +} + static gint imap_create_tree(Folder *folder) { g_return_val_if_fail(folder != NULL, -1); -- cgit v1.2.3