* src/filter.c
authorChristoph Hohmann <reboot@gmx.ch>
Thu, 25 Jul 2002 21:09:10 +0000 (21:09 +0000)
committerChristoph Hohmann <reboot@gmx.ch>
Thu, 25 Jul 2002 21:09:10 +0000 (21:09 +0000)
* src/folder.[ch]
* src/folderview.c
* src/imap.[ch]
* src/mainwindow.c
* src/mbox_folder.c
* src/mh.c
* src/news.c
        implement imap uid cache and uid validity check

12 files changed:
ChangeLog.claws
configure.in
src/filter.c
src/folder.c
src/folder.h
src/folderview.c
src/imap.c
src/imap.h
src/mainwindow.c
src/mbox_folder.c
src/mh.c
src/news.c

index 4676ee2..091c18e 100644 (file)
@@ -1,3 +1,15 @@
+2002-07-25 [christoph] 0.8.0claws13
+
+       * src/filter.c
+       * src/folder.[ch]
+       * src/folderview.c
+       * src/imap.[ch]
+       * src/mainwindow.c
+       * src/mbox_folder.c
+       * src/mh.c
+       * src/news.c
+               implement imap uid cache and uid validity check
+
 2002-07-25 [alfons]    0.8.0claws12
 
        * src/summaryview.c
index e4f88e8..295769f 100644 (file)
@@ -8,7 +8,7 @@ MINOR_VERSION=8
 MICRO_VERSION=0
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=claws12
+EXTRA_VERSION=claws13
 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION
 
 dnl set $target
index b6043b1..67d64a5 100644 (file)
@@ -52,7 +52,7 @@ FolderItem *filter_get_dest_folder(GSList *fltlist, const gchar *file)
                if (filter_match_condition(filter, hlist)) {
                        if (filter->action == FLT_NOTRECV) {
                                if (!dummy) {
-                                       dummy = folder_item_new(NULL, NULL);
+                                       dummy = g_new0(FolderItem, 0);
                                        dummy->path = g_strdup(FILTER_NOT_RECEIVE);
                                }
                                dest_folder = dummy;
index 9f4aa58..e749d65 100644 (file)
@@ -104,7 +104,6 @@ static void folder_init(Folder *folder, const gchar *name)
        folder_set_name(folder, name);
 
        /* Init folder data */
-       folder->type = F_UNKNOWN;
        folder->account = NULL;
        folder->inbox = NULL;
        folder->outbox = NULL;
@@ -122,7 +121,7 @@ static void folder_init(Folder *folder, const gchar *name)
        folder->check_msgnum_validity = NULL;
 
        /* Create root folder item */
-       item = folder_item_new(name, NULL);
+       item = folder_item_new(folder, name, NULL);
        item->folder = folder;
        folder->node = g_node_new(item);
        folder->data = NULL;
@@ -198,11 +197,24 @@ Folder *maildir_folder_new(const gchar *name, const gchar *path)
 }
 #endif
 
-FolderItem *folder_item_new(const gchar *name, const gchar *path)
+FolderItem *folder_item_new(Folder *folder, const gchar *name, const gchar *path)
 {
-       FolderItem *item;
+       FolderItem *item = NULL;
 
-       item = g_new0(FolderItem, 1);
+       switch (folder->type) {
+       case F_IMAP:
+               item = imap_folder_item_new();
+               break;
+       case F_MH:
+       case F_NEWS:
+       case F_MBOX:
+               item = g_new0(FolderItem, 1);
+               break;
+       default:
+               return NULL;
+       }
+
+       g_return_val_if_fail(item != NULL, NULL);
 
        item->stype = F_NORMAL;
        item->name = g_strdup(name);
@@ -269,7 +281,15 @@ void folder_item_destroy(FolderItem *item)
        g_return_if_fail(item != NULL);
 
        debug_print(_("Destroying folder item %s\n"), item->path);
-       
+
+       switch (item->folder->type) {
+       case F_IMAP:
+               imap_folder_item_destroy(item);
+               break;
+       default:
+               break;
+       }
+
        if(item->cache)
                folder_item_free_cache(item);
        g_free(item->name);
@@ -728,14 +748,14 @@ FolderItem *folder_get_default_trash(void)
        return folder->trash;
 }
 
-#define CREATE_FOLDER_IF_NOT_EXIST(member, dir, type)  \
-{                                                      \
-       if (!folder->member) {                          \
-               item = folder_item_new(dir, dir);       \
-               item->stype = type;                     \
-               folder_item_append(rootitem, item);     \
-               folder->member = item;                  \
-       }                                               \
+#define CREATE_FOLDER_IF_NOT_EXIST(member, dir, type)          \
+{                                                              \
+       if (!folder->member) {                                  \
+               item = folder_item_new(folder, dir, dir);       \
+               item->stype = type;                             \
+               folder_item_append(rootitem, item);             \
+               folder->member = item;                          \
+       }                                                       \
 }
 
 void folder_set_missing_folders(void)
@@ -1859,7 +1879,7 @@ static gboolean folder_build_tree(GNode *node, gpointer data)
                }
        }
 
-       item = folder_item_new(name, path);
+       item = folder_item_new(folder, name, path);
        item->stype = stype;
        item->account = account;
        item->mtime = mtime;
@@ -2178,7 +2198,7 @@ static void folder_create_processing_folder(void)
        }
        else {
                debug_print("*TMP* already created\n");
-               processing_folder_item = folder_item_new(".processing", ".processing");
+               processing_folder_item = folder_item_new(processing_folder, ".processing", ".processing");
                g_assert(processing_folder_item);
                folder_item_append(processing_folder->node->data, processing_folder_item);
        }
index d2cf511..9decece 100644 (file)
@@ -277,7 +277,8 @@ void        folder_destroy          (Folder         *folder);
 void        folder_local_folder_destroy        (LocalFolder    *lfolder);
 void        folder_remote_folder_destroy(RemoteFolder  *rfolder);
 
-FolderItem *folder_item_new    (const gchar    *name,
+FolderItem *folder_item_new    (Folder         *folder,
+                                const gchar    *name,
                                 const gchar    *path);
 void        folder_item_append (FolderItem     *parent,
                                 FolderItem     *item);
index 4ab2a4b..490b928 100644 (file)
@@ -2327,7 +2327,7 @@ static void folderview_new_news_group_cb(FolderView *folderview, guint action,
                                             FALSE, FALSE);
                gtk_ctree_expand(ctree, servernode);
 
-               newitem = folder_item_new(name, name);
+               newitem = folder_item_new(folder, name, name);
                folder_item_append(rootitem, newitem);
                gtk_ctree_node_set_row_data(ctree, node, newitem);
        }
index ee764c8..c3d32ef 100644 (file)
@@ -81,7 +81,8 @@ static IMAPSession *imap_session_get  (Folder         *folder);
 
 static gint imap_scan_tree_recursive   (IMAPSession    *session,
                                         FolderItem     *item);
-static GSList *imap_parse_list         (IMAPSession    *session,
+static GSList *imap_parse_list         (Folder         *folder,
+                                        IMAPSession    *session,
                                         const gchar    *real_path);
 
 static void imap_create_missing_folders        (Folder                 *folder);
@@ -275,7 +276,8 @@ GSList *imap_get_num_list                   (Folder         *folder,
 MsgInfo *imap_fetch_msginfo                    (Folder         *folder,
                                                 FolderItem     *item,
                                                 gint            num);
-
+gboolean imap_check_msgnum_validity            (Folder         *folder,
+                                                FolderItem     *item);
 
 Folder *imap_folder_new(const gchar *name, const gchar *path)
 {
@@ -295,33 +297,70 @@ void imap_folder_destroy(IMAPFolder *folder)
 static void imap_folder_init(Folder *folder, const gchar *name,
                             const gchar *path)
 {
-       folder_remote_folder_init(folder, name, path);
-
        folder->type = F_IMAP;
 
+       folder_remote_folder_init(folder, name, path);
+
 /*
        folder->get_msg_list        = imap_get_msg_list;
 */
-       folder->fetch_msg           = imap_fetch_msg;
-       folder->add_msg             = imap_add_msg;
-       folder->move_msg            = imap_move_msg;
-       folder->move_msgs_with_dest = imap_move_msgs_with_dest;
-       folder->copy_msg            = imap_copy_msg;
-       folder->copy_msgs_with_dest = imap_copy_msgs_with_dest;
-       folder->remove_msg          = imap_remove_msg;
-       folder->remove_all_msg      = imap_remove_all_msg;
-       folder->is_msg_changed      = imap_is_msg_changed;
+       folder->fetch_msg             = imap_fetch_msg;
+       folder->add_msg               = imap_add_msg;
+       folder->move_msg              = imap_move_msg;
+       folder->move_msgs_with_dest   = imap_move_msgs_with_dest;
+       folder->copy_msg              = imap_copy_msg;
+       folder->copy_msgs_with_dest   = imap_copy_msgs_with_dest;
+       folder->remove_msg            = imap_remove_msg;
+       folder->remove_all_msg        = imap_remove_all_msg;
+       folder->is_msg_changed        = imap_is_msg_changed;
 /*
        folder->scan                = imap_scan_folder;
 */
-       folder->scan_tree           = imap_scan_tree;
-       folder->create_tree         = imap_create_tree;
-       folder->create_folder       = imap_create_folder;
-       folder->rename_folder       = imap_rename_folder;
-       folder->remove_folder       = imap_remove_folder;
+       folder->scan_tree             = imap_scan_tree;
+       folder->create_tree           = imap_create_tree;
+       folder->create_folder         = imap_create_folder;
+       folder->rename_folder         = imap_rename_folder;
+       folder->remove_folder         = imap_remove_folder;
+       folder->check_msgnum_validity = imap_check_msgnum_validity;
+
+       folder->get_num_list          = imap_get_num_list;
+       folder->fetch_msginfo         = imap_fetch_msginfo;
+}
+
+FolderItem *imap_folder_item_new()
+{
+       IMAPFolderItem *item;
+       
+       item = g_new0(IMAPFolderItem, 1);
+       item->lastuid = 0;
+       item->uid_list = NULL;
+
+       return (FolderItem *)item;
+}
 
-       folder->get_num_list        = imap_get_num_list;
-       folder->fetch_msginfo       = imap_fetch_msginfo;
+void imap_folder_item_destroy(FolderItem *_item)
+{
+       IMAPFolderItem *item = (IMAPFolderItem *)_item;
+
+       g_return_if_fail(item != NULL);
+       g_slist_free(item->uid_list);
+}
+
+static gboolean imap_reset_uid_lists_func(GNode *node, gpointer data)
+{
+       IMAPFolderItem *item = (IMAPFolderItem *)node->data;
+       
+       item->lastuid = 0;
+       g_slist_free(item->uid_list);
+       item->uid_list = NULL;
+       
+       return FALSE;
+}
+
+static void imap_reset_uid_lists(Folder *folder)
+{
+       /* Destroy all uid lists and rest last uid */
+       g_node_traverse(folder->node, G_IN_ORDER, G_TRAVERSE_ALL, -1, imap_reset_uid_lists_func, NULL); 
 }
 
 static IMAPSession *imap_session_get(Folder *folder)
@@ -349,6 +388,7 @@ static IMAPSession *imap_session_get(Folder *folder)
                        imap_parse_namespace(IMAP_SESSION(rfolder->session),
                                             IMAP_FOLDER(folder));
                        rfolder->session->last_access_time = time(NULL);
+                       imap_reset_uid_lists(folder);
                }
                statusbar_pop_all();
                return IMAP_SESSION(rfolder->session);
@@ -375,9 +415,11 @@ static IMAPSession *imap_session_get(Folder *folder)
                session_destroy(rfolder->session);
                rfolder->session =
                        imap_session_new(folder->account);
-               if (rfolder->session)
+               if (rfolder->session) {
                        imap_parse_namespace(IMAP_SESSION(rfolder->session),
                                             IMAP_FOLDER(folder));
+                       imap_reset_uid_lists(folder);
+               }
        }
 
        if (rfolder->session)
@@ -1024,7 +1066,7 @@ void imap_scan_tree(Folder *folder)
        }
 
        folder_tree_destroy(folder);
-       item = folder_item_new(folder->name, root_folder);
+       item = folder_item_new(folder, folder->name, root_folder);
        item->folder = folder;
        folder->node = g_node_new(item);
 
@@ -1075,7 +1117,7 @@ static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item)
                          wildcard_path);
 
        strtailchomp(real_path, separator);
-       item_list = imap_parse_list(session, real_path);
+       item_list = imap_parse_list(folder, session, real_path);
        g_free(real_path);
 
        for (cur = item_list; cur != NULL; cur = cur->next) {
@@ -1117,7 +1159,7 @@ static gint imap_scan_tree_recursive(IMAPSession *session, FolderItem *item)
        return IMAP_SUCCESS;
 }
 
-static GSList *imap_parse_list(IMAPSession *session, const gchar *real_path)
+static GSList *imap_parse_list(Folder *folder, IMAPSession *session, const gchar *real_path)
 {
        gchar buf[IMAPBUFSIZE];
        gchar flags[256];
@@ -1181,7 +1223,7 @@ static GSList *imap_parse_list(IMAPSession *session, const gchar *real_path)
 
                loc_name = imap_modified_utf7_to_locale(name);
                loc_path = imap_modified_utf7_to_locale(buf);
-               new_item = folder_item_new(loc_name, loc_path);
+               new_item = folder_item_new(folder, loc_name, loc_path);
                if (strcasestr(flags, "\\Noinferiors") != NULL)
                        new_item->no_sub = TRUE;
                if (strcmp(buf, "INBOX") != 0 &&
@@ -1351,7 +1393,7 @@ FolderItem *imap_create_folder(Folder *folder, FolderItem *parent,
                }
        }
 
-       new_item = folder_item_new(new_name, dirpath);
+       new_item = folder_item_new(folder, new_name, dirpath);
        folder_item_append(parent, new_item);
        g_free(imap_path);
        g_free(dirpath);
@@ -3038,31 +3080,47 @@ static gboolean imap_rename_folder_func(GNode *node, gpointer data)
        return FALSE;
 }
 
-GSList *imap_get_num_list(Folder *folder, FolderItem *item)
+GSList *imap_get_num_list(Folder *folder, FolderItem *_item)
 {
+       IMAPFolderItem *item = (IMAPFolderItem *)_item;
        IMAPSession *session;
        GSList *msgnum_list = NULL;
-       gint i;
+       gint i, lastuid_old;
        gint ok, exists = 0, recent = 0, unseen = 0;
        guint32 uid_validity = 0;
        GPtrArray *argbuf;
+       gchar *cmdbuf = NULL;
        
        g_return_val_if_fail(folder != NULL, NULL);
        g_return_val_if_fail(item != NULL, NULL);
-       g_return_val_if_fail(item->path != NULL, NULL);
+       g_return_val_if_fail(item->item.path != NULL, NULL);
        g_return_val_if_fail(folder->type == F_IMAP, NULL);
        g_return_val_if_fail(folder->account != NULL, NULL);
 
        session = imap_session_get(folder);
        g_return_val_if_fail(session != NULL, NULL);
 
-       ok = imap_select(session, IMAP_FOLDER(folder), item->path,
+       ok = imap_select(session, IMAP_FOLDER(folder), item->item.path,
                         &exists, &recent, &unseen, &uid_validity);
        if (ok != IMAP_SUCCESS)
                return NULL;
 
+       if(item->item.mtime != uid_validity) {
+               item->lastuid = 0;
+               g_slist_free(item->uid_list);
+               item->uid_list = NULL;
+               
+               item->item.mtime = uid_validity;
+       }
+       
        argbuf = g_ptr_array_new();
-       imap_cmd_gen_send(SESSION(session)->sock, "FETCH 1:* (UID)");
+       if(item->lastuid) {
+               cmdbuf = g_strdup_printf("UID FETCH %d:* (UID)", (item->lastuid + 1));
+       } else {
+               cmdbuf = g_strdup("FETCH 1:* (UID)");
+       }
+       imap_cmd_gen_send(SESSION(session)->sock, cmdbuf);
+       g_free(cmdbuf);
        ok = imap_cmd_ok(SESSION(session)->sock, argbuf);
        if (ok != IMAP_SUCCESS) {
                ptr_array_free_strings(argbuf);
@@ -3070,14 +3128,23 @@ GSList *imap_get_num_list(Folder *folder, FolderItem *item)
                return NULL;
        }
 
+       lastuid_old = item->lastuid;
+       msgnum_list = g_slist_copy(item->uid_list);
+       debug_print("Got %d uids from cache\n", g_slist_length(msgnum_list));
        for(i = 0; i < argbuf->len; i++) {
                int ret, msgidx, msgnum;
        
                if((ret = sscanf(g_ptr_array_index(argbuf, i), "%d FETCH (UID %d)", &msgidx, &msgnum)) == 2) {
-                       msgnum_list = g_slist_prepend(msgnum_list, GINT_TO_POINTER(msgnum));
+                       if(msgnum > lastuid_old) {
+                               msgnum_list = g_slist_prepend(msgnum_list, GINT_TO_POINTER(msgnum));
+                               item->uid_list = g_slist_prepend(item->uid_list, GINT_TO_POINTER(msgnum));
+
+                               if(msgnum > item->lastuid)
+                                       item->lastuid = msgnum;
+                       }
                }
        }
-       
+
        return msgnum_list;
 }
 
@@ -3138,3 +3205,26 @@ MsgInfo *imap_fetch_msginfo(Folder *folder, FolderItem *item, gint num)
        
        return msginfo;
 }
+
+gboolean imap_check_msgnum_validity(Folder *folder, FolderItem *_item)
+{
+       IMAPSession *session;
+       IMAPFolderItem *item = (IMAPFolderItem *)_item;
+       gint ok, exists = 0, recent = 0, unseen = 0;
+       guint32 uid_next, uid_validity = 0;
+       
+       g_return_val_if_fail(folder != NULL, FALSE);
+       g_return_val_if_fail(item != NULL, FALSE);
+       g_return_val_if_fail(item->item.folder != NULL, FALSE);
+       g_return_val_if_fail(item->item.folder->type == F_IMAP, FALSE);
+
+       session = imap_session_get(folder);
+       g_return_val_if_fail(session != NULL, FALSE);
+
+       ok = imap_status(session, IMAP_FOLDER(folder), item->item.path,
+                        &exists, &recent, &uid_next, &uid_validity, &unseen);
+       if (ok != IMAP_SUCCESS)
+               return FALSE;
+
+       return item->item.mtime == uid_validity;
+}
index d425aa8..05e75e4 100644 (file)
@@ -37,6 +37,7 @@
 typedef struct _IMAPFolder     IMAPFolder;
 typedef struct _IMAPSession    IMAPSession;
 typedef struct _IMAPNameSpace  IMAPNameSpace;
+typedef struct _IMAPFolderItem IMAPFolderItem;
 
 #include "prefs_account.h"
 
@@ -67,6 +68,14 @@ struct _IMAPNameSpace
        gchar separator;
 };
 
+struct _IMAPFolderItem
+{
+       FolderItem item;
+
+       guint lastuid;
+       GSList *uid_list;
+};
+
 #define IMAP_SUCCESS   0
 #define IMAP_SOCKET    2
 #define IMAP_AUTHFAIL  3
@@ -96,6 +105,9 @@ Folder       *imap_folder_new                (const gchar    *name,
                                         const gchar    *path);
 void    imap_folder_destroy            (IMAPFolder     *folder);
 
+FolderItem *imap_folder_item_new       ();
+void imap_folder_item_destroy          (FolderItem *item);
+
 Session *imap_session_new              (const PrefsAccount *account);
 void imap_session_destroy              (IMAPSession    *session);
 void imap_session_destroy_all          (void);
index f9746dc..62c427c 100644 (file)
@@ -1506,7 +1506,7 @@ void main_window_add_mbox(MainWindow *mainwin)
 
        folder_add(folder);
 
-       item = folder_item_new(folder->name, NULL);
+       item = folder_item_new(folder, folder->name, NULL);
        item->folder = folder;
        folder->node = g_node_new(item);
 
index 9dc5651..a0d4097 100644 (file)
@@ -67,10 +67,10 @@ void mbox_folder_destroy(MBOXFolder *folder)
 
 static void mbox_folder_init(Folder *folder, const gchar *name, const gchar *path)
 {
-       folder_local_folder_init(folder, name, path);
-
        folder->type = F_MBOX;
 
+       folder_local_folder_init(folder, name, path);
+
 /*
        folder->get_msg_list        = mbox_get_msg_list;
 */
@@ -2202,7 +2202,7 @@ FolderItem *mbox_create_folder(Folder *folder, FolderItem *parent,
 
        foldername = mbox_get_folderitem_name((gchar *) name);
 
-       new_item = folder_item_new(foldername, path);
+       new_item = folder_item_new(folder, foldername, path);
        folder_item_append(parent, new_item);
 
        if (!strcmp(name, "inbox")) {
index 83075ed..2c4a765 100644 (file)
--- a/src/mh.c
+++ b/src/mh.c
@@ -126,10 +126,10 @@ void mh_folder_destroy(MHFolder *folder)
 
 static void mh_folder_init(Folder *folder, const gchar *name, const gchar *path)
 {
-       folder_local_folder_init(folder, name, path);
-
        folder->type = F_MH;
 
+       folder_local_folder_init(folder, name, path);
+
 /*
        folder->get_msg_list        = mh_get_msg_list;
 */
@@ -863,7 +863,7 @@ void mh_scan_tree(Folder *folder)
 
        g_return_if_fail(folder != NULL);
 
-       item = folder_item_new(folder->name, NULL);
+       item = folder_item_new(folder, folder->name, NULL);
        item->folder = folder;
        folder->node = g_node_new(item);
 
@@ -942,7 +942,7 @@ FolderItem *mh_create_folder(Folder *folder, FolderItem *parent,
                                   NULL);
        else
                path = g_strdup(name);
-       new_item = folder_item_new(name, path);
+       new_item = folder_item_new(folder, name, path);
        folder_item_append(parent, new_item);
        g_free(path);
 
@@ -1227,7 +1227,7 @@ static void mh_scan_tree_recursive(FolderItem *item)
                                continue;
                        }
 
-                       new_item = folder_item_new(d->d_name, entry);
+                       new_item = folder_item_new(item->folder, d->d_name, entry);
                        folder_item_append(item, new_item);
                        if (!item->path) {
                                if (!strcmp(d->d_name, INBOX_DIR)) {
index f1d3384..56c8a03 100644 (file)
@@ -129,10 +129,10 @@ void news_folder_destroy(NewsFolder *folder)
 static void news_folder_init(Folder *folder, const gchar *name,
                             const gchar *path)
 {
-       folder_remote_folder_init(folder, name, path);
-
        folder->type = F_NEWS;
 
+       folder_remote_folder_init(folder, name, path);
+
 /*
        folder->get_msg_list = news_get_article_list;
 */