* src/mh.c
[claws.git] / src / mh.c
index 1c032b77b198cfe91a233c5cfbc11960ffa8e404..5d03a5fa51500c4f26fac287c2264b32a99ff7b4 100644 (file)
--- a/src/mh.c
+++ b/src/mh.c
@@ -47,7 +47,8 @@ static GSList  *mh_get_uncached_msgs          (GHashTable     *msg_table,
                                                 FolderItem     *item);
 static MsgInfo *mh_parse_msg                   (const gchar    *file,
                                                 FolderItem     *item);
-static void    mh_scan_tree_recursive          (FolderItem     *item);
+static void    mh_scan_tree_recursive          (FolderItem     *item, 
+                                                GHashTable *pptable);
 
 static gboolean mh_rename_folder_func          (GNode          *node,
                                                 gpointer        data);
@@ -130,10 +131,35 @@ gchar *mh_fetch_msg(Folder *folder, FolderItem *item, gint num)
        return file;
 }
 
+gchar *mh_get_newmsg_filename(FolderItem *dest)
+{
+       gchar *destfile;
+       gchar *destpath;
+       gboolean found = FALSE;
+
+       destpath = folder_item_get_path(dest);
+       g_return_val_if_fail(destpath != NULL, NULL);
+       if (!is_dir_exist(destpath))
+               make_dir_hier(destpath);
+
+       do {
+               destfile = g_strdup_printf("%s%c%d", destpath, G_DIR_SEPARATOR,
+                                          dest->last_num + 1);
+               if(is_file_exist(destfile)) {
+                       dest->last_num++;
+                       g_free(destfile);
+               } else {
+                       found = TRUE;
+               }
+       } while(!found);
+       g_free(destpath);
+
+       return destfile;
+}
+
 gint mh_add_msg(Folder *folder, FolderItem *dest, const gchar *file,
                gboolean remove_source)
 {
-       gchar *destpath;
        gchar *destfile;
 
        g_return_val_if_fail(dest != NULL, -1);
@@ -144,24 +170,13 @@ gint mh_add_msg(Folder *folder, FolderItem *dest, const gchar *file,
                if (dest->last_num < 0) return -1;
        }
 
-       destpath = folder_item_get_path(dest);
-       g_return_val_if_fail(destpath != NULL, -1);
-       if (!is_dir_exist(destpath))
-               make_dir_hier(destpath);
-
-       destfile = g_strdup_printf("%s%c%d", destpath, G_DIR_SEPARATOR,
-                                  dest->last_num + 1);
+       destfile = mh_get_newmsg_filename(dest);
+       if(!destfile) return -1;
 
        if (link(file, destfile) < 0) {
-               if (EXDEV == errno) {
-                       if (copy_file(file, destfile) < 0) {
-                               g_warning(_("can't copy message %s to %s\n"),
-                                         file, destfile);
-                               g_free(destfile);
-                               return -1;
-                       }
-               } else {
-                       FILE_OP_ERROR(file, "link");
+               if (copy_file(file, destfile) < 0) {
+                       g_warning(_("can't copy message %s to %s\n"),
+                                 file, destfile);
                        g_free(destfile);
                        return -1;
                }
@@ -183,6 +198,8 @@ gint mh_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
        gchar *srcfile;
        gchar *destfile;
        FILE *fp;
+       gint filemode = 0;
+       PrefsFolderItem *prefs;
 
        g_return_val_if_fail(dest != NULL, -1);
        g_return_val_if_fail(msginfo != NULL, -1);
@@ -197,6 +214,8 @@ gint mh_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
                if (dest->last_num < 0) return -1;
        }
 
+       prefs = dest->prefs;
+
        destdir = folder_item_get_path(dest);
        if ((fp = procmsg_open_mark_file(destdir, TRUE)) == NULL)
                g_warning(_("Can't open mark file.\n"));
@@ -205,8 +224,10 @@ gint mh_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
                    msginfo->folder->path, G_DIR_SEPARATOR,
                    msginfo->msgnum, dest->path);
        srcfile = procmsg_get_message_file_path(msginfo);
-       destfile = g_strdup_printf("%s%c%d", destdir, G_DIR_SEPARATOR,
-                                  dest->last_num + 1);
+
+       destfile = mh_get_newmsg_filename(dest);
+       if(!destfile) return -1;
+
        g_free(destdir);
 
        if (move_file(srcfile, destfile) < 0) {
@@ -216,6 +237,16 @@ gint mh_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
                return -1;
        }
 
+       if (prefs && prefs->enable_folder_chmod && prefs->folder_chmod) {
+               if (chmod(destfile, prefs->folder_chmod) < 0)
+                       FILE_OP_ERROR(destfile, "chmod");
+
+               /* for mark file */
+               filemode = prefs->folder_chmod;
+               if (filemode & S_IRGRP) filemode |= S_IWGRP;
+               if (filemode & S_IROTH) filemode |= S_IWOTH;
+       }
+
        g_free(srcfile);
        g_free(destfile);
        dest->last_num++;
@@ -229,10 +260,25 @@ gint mh_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
                    dest->stype == F_QUEUE  ||
                    dest->stype == F_DRAFT  ||
                    dest->stype == F_TRASH)
-                       MSG_UNSET_FLAGS(newmsginfo.flags,
-                                       MSG_NEW|MSG_UNREAD|MSG_DELETED);
+                       MSG_UNSET_PERM_FLAGS(newmsginfo.flags,
+                                            MSG_NEW|MSG_UNREAD|MSG_DELETED);
 
                procmsg_write_flags(&newmsginfo, fp);
+
+               if (filemode) {
+#if HAVE_FCHMOD
+                       fchmod(fileno(fp), filemode);
+#else
+                       gchar *markfile;
+
+                       markfile = folder_item_get_mark_file(dest);
+                       if (markfile) {
+                               chmod(markfile, filemode);
+                               g_free(markfile);
+                       }
+#endif
+               }
+
                fclose(fp);
        }
 
@@ -247,6 +293,7 @@ gint mh_move_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist)
        FILE *fp;
        GSList *cur;
        MsgInfo *msginfo;
+       PrefsFolderItem *prefs;
 
        g_return_val_if_fail(dest != NULL, -1);
        g_return_val_if_fail(msglist != NULL, -1);
@@ -256,6 +303,8 @@ gint mh_move_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist)
                if (dest->last_num < 0) return -1;
        }
 
+       prefs = dest->prefs;
+
        destdir = folder_item_get_path(dest);
        if ((fp = procmsg_open_mark_file(destdir, TRUE)) == NULL)
                g_warning(_("Can't open mark file.\n"));
@@ -272,8 +321,8 @@ gint mh_move_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist)
                            msginfo->msgnum, dest->path);
 
                srcfile = procmsg_get_message_file_path(msginfo);
-               destfile = g_strdup_printf("%s%c%d", destdir, G_DIR_SEPARATOR,
-                                          dest->last_num + 1);
+               destfile = mh_get_newmsg_filename(dest);
+               if(!destfile) return -1;
 
                if (move_file(srcfile, destfile) < 0) {
                        g_free(srcfile);
@@ -294,8 +343,9 @@ gint mh_move_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist)
                            dest->stype == F_QUEUE  ||
                            dest->stype == F_DRAFT  ||
                            dest->stype == F_TRASH)
-                               MSG_UNSET_FLAGS(newmsginfo.flags,
-                                               MSG_NEW|MSG_UNREAD|MSG_DELETED);
+                               MSG_UNSET_PERM_FLAGS
+                                       (newmsginfo.flags,
+                                        MSG_NEW|MSG_UNREAD|MSG_DELETED);
 
                        procmsg_write_flags(&newmsginfo, fp);
                }
@@ -313,6 +363,8 @@ gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
        gchar *srcfile;
        gchar *destfile;
        FILE *fp;
+       gint filemode = 0;
+       PrefsFolderItem *prefs;
 
        g_return_val_if_fail(dest != NULL, -1);
        g_return_val_if_fail(msginfo != NULL, -1);
@@ -327,6 +379,8 @@ gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
                if (dest->last_num < 0) return -1;
        }
 
+       prefs = dest->prefs;
+
        destdir = folder_item_get_path(dest);
        if (!is_dir_exist(destdir))
                make_dir_hier(destdir);
@@ -338,17 +392,16 @@ gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
                    msginfo->folder->path, G_DIR_SEPARATOR,
                    msginfo->msgnum, dest->path);
        srcfile = procmsg_get_message_file_path(msginfo);
-       destfile = g_strdup_printf("%s%c%d", destdir, G_DIR_SEPARATOR,
-                                  dest->last_num + 1);
-       g_free(destdir);
-
-       if (is_file_exist(destfile)) {
-               g_warning(_("%s already exists."), destfile);
+       destfile = mh_get_newmsg_filename(dest);
+       if(!destfile) {
                g_free(srcfile);
-               g_free(destfile);
                if (fp) fclose(fp);
                return -1;
        }
+       
+       g_free(destdir);
+
+       dest->op_count--;
 
        if (copy_file(srcfile, destfile) < 0) {
                FILE_OP_ERROR(srcfile, "copy");
@@ -358,6 +411,16 @@ gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
                return -1;
        }
 
+       if (prefs && prefs->enable_folder_chmod && prefs->folder_chmod) {
+               if (chmod(destfile, prefs->folder_chmod) < 0)
+                       FILE_OP_ERROR(destfile, "chmod");
+
+               /* for mark file */
+               filemode = prefs->folder_chmod;
+               if (filemode & S_IRGRP) filemode |= S_IWGRP;
+               if (filemode & S_IROTH) filemode |= S_IWOTH;
+       }
+
        g_free(srcfile);
        g_free(destfile);
        dest->last_num++;
@@ -371,9 +434,24 @@ gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
                    dest->stype == F_QUEUE  ||
                    dest->stype == F_DRAFT  ||
                    dest->stype == F_TRASH)
-                       MSG_UNSET_FLAGS(newmsginfo.flags,
-                                       MSG_NEW|MSG_UNREAD|MSG_DELETED);
+                       MSG_UNSET_PERM_FLAGS(newmsginfo.flags,
+                                            MSG_NEW|MSG_UNREAD|MSG_DELETED);
                procmsg_write_flags(&newmsginfo, fp);
+
+               if (filemode) {
+#if HAVE_FCHMOD
+                       fchmod(fileno(fp), filemode);
+#else
+                       gchar *markfile;
+
+                       markfile = folder_item_get_mark_file(dest);
+                       if (markfile) {
+                               chmod(markfile, filemode);
+                               g_free(markfile);
+                       }
+#endif
+               }
+
                fclose(fp);
        }
 
@@ -461,13 +539,9 @@ gint mh_copy_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist)
                            msginfo->msgnum, dest->path);
 
                srcfile = procmsg_get_message_file_path(msginfo);
-               destfile = g_strdup_printf("%s%c%d", destdir, G_DIR_SEPARATOR,
-                                          dest->last_num + 1);
-
-               if (is_file_exist(destfile)) {
-                       g_warning(_("%s already exists."), destfile);
+               destfile = mh_get_newmsg_filename(dest);
+               if(!destfile) {
                        g_free(srcfile);
-                       g_free(destfile);
                        break;
                }
 
@@ -491,8 +565,9 @@ gint mh_copy_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist)
                            dest->stype == F_QUEUE  ||
                            dest->stype == F_DRAFT  ||
                            dest->stype == F_TRASH)
-                               MSG_UNSET_FLAGS(newmsginfo.flags,
-                                               MSG_NEW|MSG_UNREAD|MSG_DELETED);
+                               MSG_UNSET_PERM_FLAGS
+                                       (newmsginfo.flags,
+                                        MSG_NEW|MSG_UNREAD|MSG_DELETED);
                        procmsg_write_flags(&newmsginfo, fp);
                }
        }
@@ -561,6 +636,8 @@ void mh_scan_folder(Folder *folder, FolderItem *item)
 
        g_return_if_fail(item != NULL);
 
+       debug_print("mh_scan_folder(): Scanning %s ...\n", item->path);
+
        path = folder_item_get_path(item);
        g_return_if_fail(path != NULL);
        if (change_dir(path) < 0) {
@@ -612,9 +689,12 @@ void mh_scan_tree(Folder *folder)
 {
        FolderItem *item;
        gchar *rootpath;
+       GHashTable *pptable;
 
        g_return_if_fail(folder != NULL);
 
+       pptable = folder_persist_prefs_new(folder);
+
        folder_tree_destroy(folder);
        item = folder_item_new(folder->name, NULL);
        item->folder = folder;
@@ -627,7 +707,9 @@ void mh_scan_tree(Folder *folder)
        }
        g_free(rootpath);
 
-       mh_scan_tree_recursive(item);
+       mh_scan_tree_recursive(item, pptable);
+       
+       folder_persist_prefs_free(pptable);
 }
 
 #define MAKE_DIR_IF_NOT_EXIST(dir) \
@@ -883,18 +965,21 @@ static MsgInfo *mh_parse_msg(const gchar *file, FolderItem *item)
 {
        struct stat s;
        MsgInfo *msginfo;
-       MsgFlags flags = MSG_NEW|MSG_UNREAD;
+       MsgFlags flags;
+
+       flags.perm_flags = MSG_NEW|MSG_UNREAD;
+       flags.tmp_flags = 0;
 
        g_return_val_if_fail(item != NULL, NULL);
        g_return_val_if_fail(file != NULL, NULL);
 
        if (item->stype == F_QUEUE) {
-               MSG_SET_FLAGS(flags, MSG_QUEUED);
+               MSG_SET_TMP_FLAGS(flags, MSG_QUEUED);
        } else if (item->stype == F_DRAFT) {
-               MSG_SET_FLAGS(flags, MSG_DRAFT);
+               MSG_SET_TMP_FLAGS(flags, MSG_DRAFT);
        }
 
-       msginfo = procheader_parse(file, flags, FALSE);
+       msginfo = procheader_parse(file, flags, FALSE, FALSE);
        if (!msginfo) return NULL;
 
        msginfo->msgnum = atoi(file);
@@ -936,7 +1021,7 @@ static gboolean mh_is_maildir(const gchar *path)
               mh_is_maildir_one(path, "tmp");
 }
 
-static void mh_scan_tree_recursive(FolderItem *item)
+static void mh_scan_tree_recursive(FolderItem *item, GHashTable *pptable)
 {
        DIR *dp;
        struct dirent *d;
@@ -1003,7 +1088,8 @@ static void mh_scan_tree_recursive(FolderItem *item)
                                        item->folder->trash = new_item;
                                }
                        }
-                       mh_scan_tree_recursive(new_item);
+                       folder_item_restore_persist_prefs(new_item, pptable);
+                       mh_scan_tree_recursive(new_item, pptable);
                } else if (to_number(d->d_name) != -1) n_msg++;
 
                g_free(entry);