2006-04-06 [mones] 2.1.0cvs7
[claws.git] / src / folder.c
index 896e82ff044e20a2024ef51b1fa240f9401598fd..c54e4c814f58c65315d5e6075973e714312f0870 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2005 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2006 Hiroyuki Yamamoto and the Sylpheed-Claws team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,6 +31,9 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <stdlib.h>
+#ifdef WIN32
+#include <w32lib.h>
+#endif
 
 #include "folder.h"
 #include "session.h"
 #include "prefs_common.h"
 #include "prefs_account.h"
 
+/* Define possible missing constants for Windows. */
+#ifdef G_OS_WIN32
+# ifndef S_IRGRP
+# define S_IRGRP 0
+# define S_IWGRP 0
+# endif
+# ifndef S_IROTH
+# define S_IROTH 0
+# define S_IWOTH 0
+# endif
+#endif
+
 static GList *folder_list = NULL;
 static GSList *class_list = NULL;
 static GSList *folder_unloaded_list = NULL;
@@ -210,12 +225,10 @@ void folder_set_xml(Folder *folder, XMLTag *tag)
 
                if (!attr || !attr->name || !attr->value) continue;
                if (!strcmp(attr->name, "name")) {
-                       if (folder->name != NULL)
-                               g_free(folder->name);
+                       g_free(folder->name);
                        folder->name = g_strdup(attr->value);
                        if (rootitem != NULL) {
-                               if (rootitem->name != NULL)
-                                       g_free(rootitem->name);
+                               g_free(rootitem->name);
                                rootitem->name = g_strdup(attr->value);
                        }
                } else if (!strcmp(attr->name, "account_id")) {
@@ -446,12 +459,10 @@ void folder_item_set_xml(Folder *folder, FolderItem *item, XMLTag *tag)
                        else if (!g_ascii_strcasecmp(attr->value, "trash"))
                                item->stype = F_TRASH;
                } else if (!strcmp(attr->name, "name")) {
-                       if (item->name != NULL)
-                               g_free(item->name);
+                       g_free(item->name);
                        item->name = g_strdup(attr->value);
                } else if (!strcmp(attr->name, "path")) {
-                       if (item->path != NULL)
-                               g_free(item->path);
+                       g_free(item->path);
                        item->path = g_strdup(attr->value);
                } else if (!strcmp(attr->name, "mtime"))
                        item->mtime = strtoul(attr->value, NULL, 10);
@@ -707,7 +718,7 @@ gint folder_read_list(void)
        }
 
        xml_free_tree(node);
-       if (folder_list)
+       if (folder_list || folder_unloaded_list)
                return 0;
        else
                return -1;
@@ -826,11 +837,17 @@ gint folder_item_rename(FolderItem *item, gchar *newname)
 
        if (retval >= 0) {
                FolderItemUpdateData hookdata;
+               FolderUpdateData hookdata2;
 
                hookdata.item = item;
                hookdata.update_flags = F_ITEM_UPDATE_NAME;
                hookdata.msg = NULL;
                hooks_invoke(FOLDER_ITEM_UPDATE_HOOKLIST, &hookdata);
+
+               hookdata2.folder = item->folder;
+               hookdata2.item = item;
+               hookdata2.update_flags = FOLDER_RENAME_FOLDERITEM;
+               hooks_invoke(FOLDER_UPDATE_HOOKLIST, &hookdata2);
        }
 
        return retval;
@@ -1253,6 +1270,17 @@ Folder *folder_get_default_folder(void)
        return folder_list ? FOLDER(folder_list->data) : NULL;
 }
 
+gboolean folder_have_mailbox (void)
+{
+       GList *cur;
+       for (cur = folder_list; cur != NULL; cur = g_list_next(cur)) {
+               Folder *folder = FOLDER(cur->data);
+               if (folder->inbox && folder->outbox)
+                       return TRUE;
+       }
+       return FALSE;
+}
+
 FolderItem *folder_get_default_inbox(void)
 {
        GList *flist;
@@ -1495,7 +1523,8 @@ void folder_item_process_open (FolderItem *item,
 
 gint folder_item_open(FolderItem *item)
 {
-       g_return_val_if_fail(item->no_select == FALSE, -1);
+       if (item->no_select)
+               return -1;
 
        item->processing_pending = TRUE;
        folder_item_process_open (item, NULL, NULL, NULL);
@@ -1511,7 +1540,9 @@ gint folder_item_close(FolderItem *item)
        Folder *folder;
        
        g_return_val_if_fail(item != NULL, -1);
-       g_return_val_if_fail(item->no_select == FALSE, -1);
+
+       if (item->no_select)
+               return -1;
 
        if (item->new_msgs) {
                folder_item_update_freeze();
@@ -1545,7 +1576,8 @@ static MsgInfoList *get_msginfos(FolderItem *item, MsgNumberList *numlist)
 {
        MsgInfoList *msglist = NULL;
        Folder *folder = item->folder;
-       g_return_val_if_fail(item->no_select == FALSE, NULL);
+       if (item->no_select)
+               return NULL;
        
        if (folder->klass->get_msginfos != NULL)
                msglist = folder->klass->get_msginfos(folder, item, numlist);
@@ -1592,7 +1624,8 @@ static gint syncronize_flags(FolderItem *item, MsgInfoList *msglist)
                return 0;
        if(item->folder->klass->get_flags == NULL)
                return 0;
-       g_return_val_if_fail(item->no_select == FALSE, 0);
+       if (item->no_select)
+               return 0;
 
        relation = g_relation_new(2);
        g_relation_index(relation, 0, g_direct_hash, g_direct_equal);
@@ -1815,7 +1848,7 @@ gint folder_item_scan_full(FolderItem *item, gboolean filtering)
 
        folder_item_update_freeze();
        if (newmsg_list != NULL) {
-               GSList *elem;
+               GSList *elem, *to_filter = NULL;
                int total = g_slist_length(newmsg_list), cur = 0;
                
                if ((filtering == TRUE) &&
@@ -1835,10 +1868,17 @@ gint folder_item_scan_full(FolderItem *item, gboolean filtering)
                            (item->folder->account != NULL) && 
                            (item->folder->account->filter_on_recv) &&
                            procmsg_msginfo_filter(msginfo))
-                               procmsg_msginfo_free(msginfo);
+                               to_filter = g_slist_prepend(to_filter, msginfo);
                        else
                                exists_list = g_slist_prepend(exists_list, msginfo);
                }
+               filtering_move_and_copy_msgs(to_filter);
+               for (elem = to_filter; elem; elem = g_slist_next(elem)) {
+                       MsgInfo *msginfo = (MsgInfo *)elem->data;
+                       procmsg_msginfo_free(msginfo);
+               }
+
+               g_slist_free(to_filter);
                g_slist_free(newmsg_list);
 
                statusbar_progress_all(0,0,0);
@@ -1942,7 +1982,8 @@ gint folder_item_syncronize_flags(FolderItem *item)
        g_return_val_if_fail(item != NULL, -1);
        g_return_val_if_fail(item->folder != NULL, -1);
        g_return_val_if_fail(item->folder->klass != NULL, -1);
-       g_return_val_if_fail(item->no_select == FALSE, -1);     
+       if (item->no_select)
+               return -1;
 
        if (item->cache == NULL)
                folder_item_read_cache(item);
@@ -2129,7 +2170,8 @@ MsgInfo *folder_item_get_msginfo(FolderItem *item, gint num)
        MsgInfo *msginfo = NULL;
        
        g_return_val_if_fail(item != NULL, NULL);
-       g_return_val_if_fail(item->no_select == FALSE, NULL);   
+       if (item->no_select)
+               return NULL;
        folder = item->folder;
        if (!item->cache)
                folder_item_read_cache(item);
@@ -2153,7 +2195,8 @@ MsgInfo *folder_item_get_msginfo_by_msgid(FolderItem *item, const gchar *msgid)
        
        g_return_val_if_fail(item != NULL, NULL);
        g_return_val_if_fail(msgid != NULL, NULL);
-       g_return_val_if_fail(item->no_select == FALSE, FALSE);
+       if (item->no_select)
+               return FALSE;
        
        folder = item->folder;
        if (!item->cache)
@@ -2168,7 +2211,8 @@ MsgInfo *folder_item_get_msginfo_by_msgid(FolderItem *item, const gchar *msgid)
 GSList *folder_item_get_msg_list(FolderItem *item)
 {
        g_return_val_if_fail(item != NULL, NULL);
-       g_return_val_if_fail(item->no_select == FALSE, FALSE);
+       if (item->no_select)
+               return FALSE;
        
        if (item->cache == 0)
                folder_item_read_cache(item);
@@ -2221,7 +2265,8 @@ gchar *folder_item_fetch_msg(FolderItem *item, gint num)
        folder = item->folder;
 
        g_return_val_if_fail(folder->klass->fetch_msg != NULL, NULL);
-       g_return_val_if_fail(item->no_select == FALSE, NULL);
+       if (item->no_select)
+               return NULL;
 
        msgfile = folder->klass->fetch_msg(folder, item, num);
 
@@ -2256,7 +2301,8 @@ gchar *folder_item_fetch_msg_full(FolderItem *item, gint num, gboolean headers,
        MsgInfo *msginfo;
 
        g_return_val_if_fail(item != NULL, NULL);
-       g_return_val_if_fail(item->no_select == FALSE, NULL);
+       if (item->no_select)
+               return NULL;
        
        folder = item->folder;
 
@@ -2300,7 +2346,8 @@ gint folder_item_fetch_all_msg(FolderItem *item)
        gint total = 0;
 
        g_return_val_if_fail(item != NULL, -1);
-       g_return_val_if_fail(item->no_select == FALSE, -1);
+       if (item->no_select)
+               return -1;
 
        debug_print("fetching all messages in %s ...\n", item->path ? item->path : "(null)");
        statusbar_print_all(_("Fetching all messages in %s ...\n"), item->path ? item->path : "(null)");
@@ -2499,7 +2546,8 @@ gint folder_item_add_msgs(FolderItem *dest, GSList *file_list,
         g_return_val_if_fail(dest != NULL, -1);
         g_return_val_if_fail(file_list != NULL, -1);
         g_return_val_if_fail(dest->folder != NULL, -1);
-       g_return_val_if_fail(dest->no_select == FALSE, -1);
+       if (dest->no_select)
+               return -1;
 
         folder = dest->folder;
 
@@ -2635,8 +2683,10 @@ FolderItem *folder_item_move_recursive(FolderItem *src, FolderItem *dest)
                src->folder->klass->remove_folder(src->folder, src);
        folder_write_list();
 
-       if (old_id != NULL && new_id != NULL)
+       if (old_id != NULL && new_id != NULL) {
                prefs_filtering_rename_path(old_id, new_id);
+               account_rename_path(old_id, new_id);
+       }
        g_free(old_id);
        g_free(new_id);
        
@@ -2721,7 +2771,8 @@ static gint do_copy_msgs(FolderItem *dest, GSList *msglist, gboolean remove_sour
        folder = dest->folder;
 
        g_return_val_if_fail(folder->klass->copy_msg != NULL, -1);
-       g_return_val_if_fail(dest->no_select == FALSE, -1);
+       if (dest->no_select)
+               return -1;
 
        relation = g_relation_new(2);
        g_relation_index(relation, 0, g_direct_hash, g_direct_equal);
@@ -2853,6 +2904,11 @@ static gint do_copy_msgs(FolderItem *dest, GSList *msglist, gboolean remove_sour
                            == POP3_PARTIAL_DLOAD_DLOAD) {
                                partial_mark_for_download(newmsginfo);
                        }
+                       if (!MSG_IS_POSTFILTERED (msginfo->flags)) {
+                           procmsg_msginfo_set_flags (   msginfo, MSG_POSTFILTERED, 0);
+                           procmsg_msginfo_set_flags (newmsginfo, MSG_POSTFILTERED, 0);
+                           hooks_invoke (MAIL_POSTFILTERING_HOOKLIST, newmsginfo);
+                       }
                        procmsg_msginfo_free(newmsginfo);
 
 
@@ -2952,7 +3008,8 @@ gint folder_item_remove_msg(FolderItem *item, gint num)
        g_return_val_if_fail(item != NULL, -1);
        folder = item->folder;
        g_return_val_if_fail(folder->klass->remove_msg != NULL, -1);
-       g_return_val_if_fail(item->no_select == FALSE, -1);
+       if (item->no_select)
+               return -1;
 
        if (!item->cache) folder_item_read_cache(item);
 
@@ -2975,7 +3032,8 @@ gint folder_item_remove_msgs(FolderItem *item, GSList *msglist)
        g_return_val_if_fail(item != NULL, -1);
        folder = item->folder;
        g_return_val_if_fail(folder != NULL, -1);
-       g_return_val_if_fail(item->no_select == FALSE, -1);
+       if (item->no_select)
+               return -1;
        inc_lock();
        if (!item->cache) folder_item_read_cache(item);
 
@@ -3010,7 +3068,8 @@ gint folder_item_remove_all_msg(FolderItem *item)
        gint result;
 
        g_return_val_if_fail(item != NULL, -1);
-       g_return_val_if_fail(item->no_select == FALSE, -1);
+       if (item->no_select)
+               return -1;
 
        folder = item->folder;
 
@@ -3047,7 +3106,8 @@ void folder_item_change_msg_flags(FolderItem *item, MsgInfo *msginfo, MsgPermFla
 {
        g_return_if_fail(item != NULL);
        g_return_if_fail(msginfo != NULL);
-       g_return_if_fail(item->no_select == FALSE);
+       if (item->no_select)
+               return;
        
        if (item->folder->klass->change_flags != NULL) {
                item->folder->klass->change_flags(item->folder, item, msginfo, newflags);
@@ -3061,7 +3121,8 @@ gboolean folder_item_is_msg_changed(FolderItem *item, MsgInfo *msginfo)
        Folder *folder;
 
        g_return_val_if_fail(item != NULL, FALSE);
-       g_return_val_if_fail(item->no_select == FALSE, FALSE);
+       if (item->no_select)
+               return FALSE;
 
        folder = item->folder;
 
@@ -3350,7 +3411,10 @@ static void folder_create_processing_folder(void)
        g_assert(processing_folder != NULL);
 
        debug_print("tmpparentroot %s\n", LOCAL_FOLDER(processing_folder)->rootpath);
-       if (LOCAL_FOLDER(processing_folder)->rootpath[0] == '/')
+        /* FIXME: [W32] The code below does not correctly merge
+           relative filenames; there should be a function to handle
+           this.  */
+       if (!is_relative_filename(LOCAL_FOLDER(processing_folder)->rootpath))
                tmpname = g_strconcat(LOCAL_FOLDER(processing_folder)->rootpath,
                                      G_DIR_SEPARATOR_S, PROCESSING_FOLDER_ITEM,
                                      NULL);
@@ -3473,10 +3537,8 @@ static void folder_get_persist_prefs_recursive(GNode *node, GHashTable *pptable)
 
 static gboolean persist_prefs_free(gpointer key, gpointer val, gpointer data)
 {
-       if (key) 
-               g_free(key);
-       if (val) 
-               g_free(val);
+       g_free(key);
+       g_free(val);
        return TRUE;    
 }
 
@@ -3487,9 +3549,16 @@ void folder_item_apply_processing(FolderItem *item)
        guint total = 0, curmsg = 0;
 
        g_return_if_fail(item != NULL);
-       g_return_if_fail(item->no_select == FALSE);     
+
+       if (item->no_select)
+              return;
+
        processing_list = item->prefs->processing;
 
+       if (!pre_global_processing && !processing_list
+       &&  !post_global_processing)
+               return;
+
        folder_item_update_freeze();
 
        mlist = folder_item_get_msg_list(item);
@@ -3508,13 +3577,19 @@ void folder_item_apply_processing(FolderItem *item)
 
                 /* apply pre global rules */
                filter_message_by_msginfo(pre_global_processing, msginfo);
-                
+               
                 /* apply rules of the folder */
                filter_message_by_msginfo(processing_list, msginfo);
 
                 /* apply post global rules */
                filter_message_by_msginfo(post_global_processing, msginfo);
                 
+       }
+       if (pre_global_processing || processing_list
+           || post_global_processing)
+               filtering_move_and_copy_msgs(mlist);
+       for (cur = mlist ; cur != NULL ; cur = cur->next) {
+               MsgInfo * msginfo = (MsgInfo *)cur->data;
                procmsg_msginfo_free(msginfo);
        }
        g_slist_free(mlist);
@@ -3628,10 +3703,8 @@ static void folder_item_want_synchronise_func(FolderItem *item, gpointer data)
        WantSyncData *want_sync_data = (WantSyncData *)data;
        
        if (want_sync_data->folder == NULL || item->folder == want_sync_data->folder) {
-               if(item->prefs->offlinesync && item->folder->klass->synchronise)
-                       want_sync_data->want_sync = TRUE;
-               else
-                       want_sync_data->want_sync = FALSE;
+               if (item->prefs->offlinesync && item->folder->klass->synchronise)
+                       want_sync_data->want_sync |= TRUE;
        }
 }
 
@@ -3640,6 +3713,7 @@ gboolean folder_want_synchronise(Folder *folder)
        WantSyncData *want_sync_data = g_new0(WantSyncData, 1);
        gboolean result;
        want_sync_data->folder = folder;
+       want_sync_data->want_sync = FALSE;
        
        folder_func_to_all_folders(folder_item_want_synchronise_func, want_sync_data);
        result = want_sync_data->want_sync;
@@ -3728,4 +3802,18 @@ gboolean folder_has_parent_of_type(FolderItem *item,
        return FALSE;
 }
 
+gboolean folder_subscribe (const gchar *uri)
+{
+       GList *cur;
+       for (cur = folder_get_list(); cur != NULL; cur = g_list_next(cur)) {
+               Folder *folder = (Folder *) cur->data;
+
+               if (folder->klass->subscribe
+               &&  folder->klass->subscribe(folder, uri)) {
+                       return TRUE;
+               }
+       }
+       return FALSE;
+
+}
 #undef PUT_ESCAPE_STR