From 3bf24b9336184fe9e28f7e09b9c5200a5f82b7d2 Mon Sep 17 00:00:00 2001 From: hiro Date: Mon, 5 Sep 2005 10:00:53 +0000 Subject: moved more modules to libsylph. git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@548 ee746299-78ed-0310-b773-934348b2243d --- src/mh.c | 1431 -------------------------------------------------------------- 1 file changed, 1431 deletions(-) delete mode 100644 src/mh.c (limited to 'src/mh.c') diff --git a/src/mh.c b/src/mh.c deleted file mode 100644 index 40554867..00000000 --- a/src/mh.c +++ /dev/null @@ -1,1431 +0,0 @@ -/* - * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client - * Copyright (C) 1999-2005 Hiroyuki Yamamoto - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "defs.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#undef MEASURE_TIME - -#include "folder.h" -#include "mh.h" -#include "procmsg.h" -#include "procheader.h" -#include "utils.h" -#include "prefs_common.h" - -static void mh_folder_init (Folder *folder, - const gchar *name, - const gchar *path); - -static Folder *mh_folder_new (const gchar *name, - const gchar *path); -static void mh_folder_destroy (Folder *folder); - -static GSList *mh_get_msg_list (Folder *folder, - FolderItem *item, - gboolean use_cache); -static gchar *mh_fetch_msg (Folder *folder, - FolderItem *item, - gint num); -static MsgInfo *mh_get_msginfo (Folder *folder, - FolderItem *item, - gint num); -static gint mh_add_msg (Folder *folder, - FolderItem *dest, - const gchar *file, - MsgFlags *flags, - gboolean remove_source); -static gint mh_add_msgs (Folder *folder, - FolderItem *dest, - GSList *file_list, - gboolean remove_source, - gint *first); -static gint mh_move_msg (Folder *folder, - FolderItem *dest, - MsgInfo *msginfo); -static gint mh_move_msgs (Folder *folder, - FolderItem *dest, - GSList *msglist); -static gint mh_copy_msg (Folder *folder, - FolderItem *dest, - MsgInfo *msginfo); -static gint mh_copy_msgs (Folder *folder, - FolderItem *dest, - GSList *msglist); -static gint mh_remove_msg (Folder *folder, - FolderItem *item, - MsgInfo *msginfo); -static gint mh_remove_all_msg (Folder *folder, - FolderItem *item); -static gboolean mh_is_msg_changed (Folder *folder, - FolderItem *item, - MsgInfo *msginfo); -static gint mh_close (Folder *folder, - FolderItem *item); - -static gint mh_scan_folder_full (Folder *folder, - FolderItem *item, - gboolean count_sum); -static gint mh_scan_folder (Folder *folder, - FolderItem *item); -static gint mh_scan_tree (Folder *folder); - -static gint mh_create_tree (Folder *folder); -static FolderItem *mh_create_folder (Folder *folder, - FolderItem *parent, - const gchar *name); -static gint mh_rename_folder (Folder *folder, - FolderItem *item, - const gchar *name); -static gint mh_move_folder (Folder *folder, - FolderItem *item, - FolderItem *new_parent); -static gint mh_remove_folder (Folder *folder, - FolderItem *item); - -static gchar *mh_get_new_msg_filename (FolderItem *dest); - -static gint mh_do_move_msgs (Folder *folder, - FolderItem *dest, - GSList *msglist); - -static time_t mh_get_mtime (FolderItem *item); -static GSList *mh_get_uncached_msgs (GHashTable *msg_table, - FolderItem *item); -static MsgInfo *mh_parse_msg (const gchar *file, - FolderItem *item); -static void mh_remove_missing_folder_items (Folder *folder); -static void mh_scan_tree_recursive (FolderItem *item); - -static gboolean mh_rename_folder_func (GNode *node, - gpointer data); - -static FolderClass mh_class = -{ - F_MH, - - mh_folder_new, - mh_folder_destroy, - - mh_scan_tree, - mh_create_tree, - - mh_get_msg_list, - mh_fetch_msg, - mh_get_msginfo, - mh_add_msg, - mh_add_msgs, - mh_move_msg, - mh_move_msgs, - mh_copy_msg, - mh_copy_msgs, - mh_remove_msg, - NULL, - mh_remove_all_msg, - mh_is_msg_changed, - mh_close, - mh_scan_folder, - - mh_create_folder, - mh_rename_folder, - mh_move_folder, - mh_remove_folder, -}; - - -FolderClass *mh_get_class(void) -{ - return &mh_class; -} - -static Folder *mh_folder_new(const gchar *name, const gchar *path) -{ - Folder *folder; - - folder = (Folder *)g_new0(MHFolder, 1); - mh_folder_init(folder, name, path); - - return folder; -} - -static void mh_folder_destroy(Folder *folder) -{ - folder_local_folder_destroy(LOCAL_FOLDER(folder)); -} - -static void mh_folder_init(Folder *folder, const gchar *name, const gchar *path) -{ - folder->klass = mh_get_class(); - folder_local_folder_init(folder, name, path); -} - -static GSList *mh_get_msg_list(Folder *folder, FolderItem *item, - gboolean use_cache) -{ - GSList *mlist; - GHashTable *msg_table; - time_t cur_mtime; -#ifdef MEASURE_TIME - GTimer *timer; -#endif - - g_return_val_if_fail(item != NULL, NULL); - -#ifdef MEASURE_TIME - timer = g_timer_new(); -#endif - - cur_mtime = mh_get_mtime(item); - - if (use_cache && item->mtime == cur_mtime) { - debug_print("Folder is not modified.\n"); - mlist = procmsg_read_cache(item, FALSE); - if (!mlist) { - mlist = mh_get_uncached_msgs(NULL, item); - if (mlist) - item->cache_dirty = TRUE; - } - } else if (use_cache) { - GSList *newlist, *cur, *next; - gboolean strict_cache_check = prefs_common.strict_cache_check; - - if (item->stype == F_QUEUE || item->stype == F_DRAFT) - strict_cache_check = TRUE; - - mlist = procmsg_read_cache(item, strict_cache_check); - msg_table = procmsg_msg_hash_table_create(mlist); - newlist = mh_get_uncached_msgs(msg_table, item); - if (newlist) - item->cache_dirty = TRUE; - if (msg_table) - g_hash_table_destroy(msg_table); - - if (!strict_cache_check) { - /* remove nonexistent messages */ - for (cur = mlist; cur != NULL; cur = next) { - MsgInfo *msginfo = (MsgInfo *)cur->data; - next = cur->next; - if (!MSG_IS_CACHED(msginfo->flags)) { - debug_print("removing nonexistent message %d from cache\n", msginfo->msgnum); - mlist = g_slist_remove(mlist, msginfo); - procmsg_msginfo_free(msginfo); - item->cache_dirty = TRUE; - item->mark_dirty = TRUE; - } - } - } - - mlist = g_slist_concat(mlist, newlist); - } else { - mlist = mh_get_uncached_msgs(NULL, item); - item->cache_dirty = TRUE; - } - - item->mtime = cur_mtime; - - procmsg_set_flags(mlist, item); - - mlist = procmsg_sort_msg_list(mlist, item->sort_key, item->sort_type); - -#ifdef MEASURE_TIME - g_timer_stop(timer); - g_print("%s: %s: elapsed time: %f sec\n", - G_STRFUNC, item->path, g_timer_elapsed(timer, NULL)); - g_timer_destroy(timer); -#endif - debug_print("cache_dirty: %d, mark_dirty: %d\n", - item->cache_dirty, item->mark_dirty); - - return mlist; -} - -static gchar *mh_fetch_msg(Folder *folder, FolderItem *item, gint num) -{ - gchar *path; - gchar *file; - - g_return_val_if_fail(item != NULL, NULL); - g_return_val_if_fail(num > 0, NULL); - - if (item->last_num < 0 || num > item->last_num) { - mh_scan_folder(folder, item); - if (item->last_num < 0) return NULL; - } - - g_return_val_if_fail(num <= item->last_num, NULL); - - path = folder_item_get_path(item); - file = g_strconcat(path, G_DIR_SEPARATOR_S, itos(num), NULL); - g_free(path); - if (!is_file_exist(file)) { - g_free(file); - return NULL; - } - - return file; -} - -static MsgInfo *mh_get_msginfo(Folder *folder, FolderItem *item, gint num) -{ - MsgInfo *msginfo; - gchar *file; - - g_return_val_if_fail(item != NULL, NULL); - g_return_val_if_fail(num > 0, NULL); - - file = mh_fetch_msg(folder, item, num); - if (!file) return NULL; - - msginfo = mh_parse_msg(file, item); - if (msginfo) - msginfo->msgnum = num; - - g_free(file); - - return msginfo; -} - -static gchar *mh_get_new_msg_filename(FolderItem *dest) -{ - gchar *destfile; - gchar *destpath; - - destpath = folder_item_get_path(dest); - g_return_val_if_fail(destpath != NULL, NULL); - - if (!is_dir_exist(destpath)) - make_dir_hier(destpath); - - for (;;) { - destfile = g_strdup_printf("%s%c%d", destpath, G_DIR_SEPARATOR, - dest->last_num + 1); - if (is_file_entry_exist(destfile)) { - dest->last_num++; - g_free(destfile); - } else - break; - } - - g_free(destpath); - - return destfile; -} - -#define SET_DEST_MSG_FLAGS(fp, dest, n, fl) \ -{ \ - MsgInfo newmsginfo; \ - \ - newmsginfo.msgnum = n; \ - newmsginfo.flags = fl; \ - if (dest->stype == F_OUTBOX || \ - dest->stype == F_QUEUE || \ - dest->stype == F_DRAFT || \ - dest->stype == F_TRASH) \ - MSG_UNSET_PERM_FLAGS(newmsginfo.flags, \ - MSG_NEW|MSG_UNREAD|MSG_DELETED); \ - \ - if (fp) \ - procmsg_write_flags(&newmsginfo, fp); \ - else if (dest->opened) \ - procmsg_add_flags(dest, n, newmsginfo.flags); \ -} - -static gint mh_add_msg(Folder *folder, FolderItem *dest, const gchar *file, - MsgFlags *flags, gboolean remove_source) -{ - GSList file_list; - MsgFileInfo fileinfo; - - g_return_val_if_fail(file != NULL, -1); - - fileinfo.file = (gchar *)file; - fileinfo.flags = flags; - file_list.data = &fileinfo; - file_list.next = NULL; - - return mh_add_msgs(folder, dest, &file_list, remove_source, NULL); -} - -static gint mh_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list, - gboolean remove_source, gint *first) -{ - gchar *destfile; - GSList *cur; - MsgFileInfo *fileinfo; - gint first_ = 0; - FILE *fp; - - g_return_val_if_fail(dest != NULL, -1); - g_return_val_if_fail(file_list != NULL, -1); - - if (dest->last_num < 0) { - mh_scan_folder(folder, dest); - if (dest->last_num < 0) return -1; - } - - if ((((MsgFileInfo *)file_list->data)->flags == NULL && - file_list->next == NULL) || dest->opened) - fp = NULL; - else if ((fp = procmsg_open_mark_file(dest, DATA_APPEND)) == NULL) - g_warning("Can't open mark file.\n"); - - for (cur = file_list; cur != NULL; cur = cur->next) { - fileinfo = (MsgFileInfo *)cur->data; - - destfile = mh_get_new_msg_filename(dest); - if (destfile == NULL) return -1; - if (first_ == 0 || first_ > dest->last_num + 1) - first_ = dest->last_num + 1; - -#ifdef G_OS_UNIX - if (link(fileinfo->file, destfile) < 0) { -#endif - if (copy_file(fileinfo->file, destfile, TRUE) < 0) { - g_warning(_("can't copy message %s to %s\n"), - fileinfo->file, destfile); - g_free(destfile); - return -1; - } -#ifdef G_OS_UNIX - } -#endif - - g_free(destfile); - dest->last_num++; - dest->total++; - dest->updated = TRUE; - - if (fileinfo->flags) { - if (MSG_IS_RECEIVED(*fileinfo->flags)) { - if (dest->unmarked_num == 0) - dest->new = 0; - dest->unmarked_num++; - procmsg_add_mark_queue(dest, dest->last_num, - *fileinfo->flags); - } else { - SET_DEST_MSG_FLAGS(fp, dest, dest->last_num, - *fileinfo->flags); - } - if (MSG_IS_NEW(*fileinfo->flags)) - dest->new++; - if (MSG_IS_UNREAD(*fileinfo->flags)) - dest->unread++; - } else { - if (dest->unmarked_num == 0) - dest->new = 0; - dest->unmarked_num++; - dest->new++; - dest->unread++; - } - } - - if (fp) fclose(fp); - - if (first) - *first = first_; - - if (remove_source) { - for (cur = file_list; cur != NULL; cur = cur->next) { - fileinfo = (MsgFileInfo *)cur->data; - if (g_unlink(fileinfo->file) < 0) - FILE_OP_ERROR(fileinfo->file, "unlink"); - } - } - - return dest->last_num; -} - -static gint mh_do_move_msgs(Folder *folder, FolderItem *dest, GSList *msglist) -{ - FolderItem *src; - gchar *srcfile; - gchar *destfile; - FILE *fp; - GSList *cur; - MsgInfo *msginfo; - - g_return_val_if_fail(dest != NULL, -1); - g_return_val_if_fail(msglist != NULL, -1); - - if (dest->last_num < 0) { - mh_scan_folder(folder, dest); - if (dest->last_num < 0) return -1; - } - - if (dest->opened) - fp = NULL; - else if ((fp = procmsg_open_mark_file(dest, DATA_APPEND)) == NULL) - g_warning(_("Can't open mark file.\n")); - - for (cur = msglist; cur != NULL; cur = cur->next) { - msginfo = (MsgInfo *)cur->data; - src = msginfo->folder; - - if (src == dest) { - g_warning(_("the src folder is identical to the dest.\n")); - continue; - } - debug_print("Moving message %s%c%d to %s ...\n", - src->path, G_DIR_SEPARATOR, msginfo->msgnum, - dest->path); - - destfile = mh_get_new_msg_filename(dest); - if (!destfile) break; - srcfile = procmsg_get_message_file(msginfo); - - if (move_file(srcfile, destfile, FALSE) < 0) { - g_free(srcfile); - g_free(destfile); - break; - } - - g_free(srcfile); - g_free(destfile); - src->total--; - src->updated = TRUE; - dest->last_num++; - dest->total++; - dest->updated = TRUE; - - if (fp) { - SET_DEST_MSG_FLAGS(fp, dest, dest->last_num, - msginfo->flags); - } - - if (MSG_IS_NEW(msginfo->flags)) { - src->new--; - dest->new++; - } - if (MSG_IS_UNREAD(msginfo->flags)) { - src->unread--; - dest->unread++; - } - - MSG_SET_TMP_FLAGS(msginfo->flags, MSG_INVALID); - } - - if (fp) fclose(fp); - - return dest->last_num; -} - -static gint mh_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo) -{ - GSList msglist; - - g_return_val_if_fail(msginfo != NULL, -1); - - msglist.data = msginfo; - msglist.next = NULL; - - return mh_move_msgs(folder, dest, &msglist); -} - -static gint mh_move_msgs(Folder *folder, FolderItem *dest, GSList *msglist) -{ - MsgInfo *msginfo; - GSList *file_list; - gint ret = 0; - gint first; - - msginfo = (MsgInfo *)msglist->data; - if (folder == msginfo->folder->folder) - return mh_do_move_msgs(folder, dest, msglist); - - file_list = procmsg_get_message_file_list(msglist); - g_return_val_if_fail(file_list != NULL, -1); - - ret = mh_add_msgs(folder, dest, file_list, FALSE, &first); - - procmsg_message_file_list_free(file_list); - - if (ret != -1) - ret = folder_item_remove_msgs(msginfo->folder, msglist); - - return ret; -} - -static gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo) -{ - GSList msglist; - - g_return_val_if_fail(msginfo != NULL, -1); - - msglist.data = msginfo; - msglist.next = NULL; - - return mh_copy_msgs(folder, dest, &msglist); -} - -static gint mh_copy_msgs(Folder *folder, FolderItem *dest, GSList *msglist) -{ - gchar *srcfile; - gchar *destfile; - FILE *fp; - GSList *cur; - MsgInfo *msginfo; - - g_return_val_if_fail(dest != NULL, -1); - g_return_val_if_fail(msglist != NULL, -1); - - if (dest->last_num < 0) { - mh_scan_folder(folder, dest); - if (dest->last_num < 0) return -1; - } - - if (dest->opened) - fp = NULL; - else if ((fp = procmsg_open_mark_file(dest, DATA_APPEND)) == NULL) - g_warning(_("Can't open mark file.\n")); - - for (cur = msglist; cur != NULL; cur = cur->next) { - msginfo = (MsgInfo *)cur->data; - - if (msginfo->folder == dest) { - g_warning(_("the src folder is identical to the dest.\n")); - continue; - } - debug_print(_("Copying message %s%c%d to %s ...\n"), - msginfo->folder->path, G_DIR_SEPARATOR, - msginfo->msgnum, dest->path); - - destfile = mh_get_new_msg_filename(dest); - if (!destfile) break; - srcfile = procmsg_get_message_file(msginfo); - - if (copy_file(srcfile, destfile, TRUE) < 0) { - FILE_OP_ERROR(srcfile, "copy"); - g_free(srcfile); - g_free(destfile); - break; - } - - g_free(srcfile); - g_free(destfile); - dest->last_num++; - dest->total++; - dest->updated = TRUE; - - if (fp) { - SET_DEST_MSG_FLAGS(fp, dest, dest->last_num, - msginfo->flags); - } - - if (MSG_IS_NEW(msginfo->flags)) - dest->new++; - if (MSG_IS_UNREAD(msginfo->flags)) - dest->unread++; - } - - if (fp) fclose(fp); - - return dest->last_num; -} - -static gint mh_remove_msg(Folder *folder, FolderItem *item, MsgInfo *msginfo) -{ - gchar *file; - - g_return_val_if_fail(item != NULL, -1); - - file = mh_fetch_msg(folder, item, msginfo->msgnum); - g_return_val_if_fail(file != NULL, -1); - - if (g_unlink(file) < 0) { - FILE_OP_ERROR(file, "unlink"); - g_free(file); - return -1; - } - g_free(file); - - item->total--; - item->updated = TRUE; - if (MSG_IS_NEW(msginfo->flags)) - item->new--; - if (MSG_IS_UNREAD(msginfo->flags)) - item->unread--; - MSG_SET_TMP_FLAGS(msginfo->flags, MSG_INVALID); - - if (msginfo->msgnum == item->last_num) - mh_scan_folder_full(folder, item, FALSE); - - return 0; -} - -static gint mh_remove_all_msg(Folder *folder, FolderItem *item) -{ - gchar *path; - gint val; - - g_return_val_if_fail(item != NULL, -1); - - path = folder_item_get_path(item); - g_return_val_if_fail(path != NULL, -1); - val = remove_all_numbered_files(path); - g_free(path); - if (val == 0) { - item->new = item->unread = item->total = 0; - item->last_num = 0; - item->updated = TRUE; - } - - return val; -} - -static gboolean mh_is_msg_changed(Folder *folder, FolderItem *item, - MsgInfo *msginfo) -{ - struct stat s; - - if (g_stat(itos(msginfo->msgnum), &s) < 0 || - msginfo->size != s.st_size || - msginfo->mtime != s.st_mtime) - return TRUE; - - return FALSE; -} - -static gint mh_close(Folder *folder, FolderItem *item) -{ - return 0; -} - -static gint mh_scan_folder_full(Folder *folder, FolderItem *item, - gboolean count_sum) -{ - gchar *path; - DIR *dp; - struct dirent *d; - gint max = 0; - gint num; - gint n_msg = 0; - - g_return_val_if_fail(item != NULL, -1); - - debug_print("mh_scan_folder(): Scanning %s ...\n", item->path); - - path = folder_item_get_path(item); - g_return_val_if_fail(path != NULL, -1); - if (change_dir(path) < 0) { - g_free(path); - return -1; - } - g_free(path); - - if ((dp = opendir(".")) == NULL) { - FILE_OP_ERROR(item->path, "opendir"); - return -1; - } - - if (folder->ui_func) - folder->ui_func(folder, item, folder->ui_func_data); - - while ((d = readdir(dp)) != NULL) { - if ((num = to_number(d->d_name)) > 0 && - dirent_is_regular_file(d)) { - n_msg++; - if (max < num) - max = num; - } - } - - closedir(dp); - - if (n_msg == 0) - item->new = item->unread = item->total = 0; - else if (count_sum) { - gint new, unread, total, min, max_; - - procmsg_get_mark_sum - (item, &new, &unread, &total, &min, &max_, 0); - - if (n_msg > total) { - item->unmarked_num = new = n_msg - total; - unread += n_msg - total; - } else - item->unmarked_num = 0; - - item->new = new; - item->unread = unread; - item->total = n_msg; - } - - item->updated = TRUE; - - debug_print(_("Last number in dir %s = %d\n"), item->path, max); - item->last_num = max; - - return 0; -} - -static gint mh_scan_folder(Folder *folder, FolderItem *item) -{ - return mh_scan_folder_full(folder, item, TRUE); -} - -static gint mh_scan_tree(Folder *folder) -{ - FolderItem *item; - gchar *rootpath; - - g_return_val_if_fail(folder != NULL, -1); - - if (!folder->node) { - item = folder_item_new(folder->name, NULL); - item->folder = folder; - folder->node = item->node = g_node_new(item); - } else - item = FOLDER_ITEM(folder->node->data); - - rootpath = folder_item_get_path(item); - if (change_dir(rootpath) < 0) { - g_free(rootpath); - return -1; - } - g_free(rootpath); - - mh_create_tree(folder); - mh_remove_missing_folder_items(folder); - mh_scan_tree_recursive(item); - - return 0; -} - -#define MAKE_DIR_IF_NOT_EXIST(dir) \ -{ \ - if (!is_dir_exist(dir)) { \ - if (is_file_exist(dir)) { \ - g_warning(_("File `%s' already exists.\n" \ - "Can't create folder."), dir); \ - return -1; \ - } \ - if (make_dir(dir) < 0) \ - return -1; \ - } \ -} - -static gint mh_create_tree(Folder *folder) -{ - gchar *rootpath; - - g_return_val_if_fail(folder != NULL, -1); - - CHDIR_RETURN_VAL_IF_FAIL(get_mail_base_dir(), -1); - rootpath = LOCAL_FOLDER(folder)->rootpath; - MAKE_DIR_IF_NOT_EXIST(rootpath); - CHDIR_RETURN_VAL_IF_FAIL(rootpath, -1); - MAKE_DIR_IF_NOT_EXIST(INBOX_DIR); - MAKE_DIR_IF_NOT_EXIST(OUTBOX_DIR); - MAKE_DIR_IF_NOT_EXIST(QUEUE_DIR); - MAKE_DIR_IF_NOT_EXIST(DRAFT_DIR); - MAKE_DIR_IF_NOT_EXIST(TRASH_DIR); - - return 0; -} - -#undef MAKE_DIR_IF_NOT_EXIST - -static FolderItem *mh_create_folder(Folder *folder, FolderItem *parent, - const gchar *name) -{ - gchar *path; - gchar *fs_name; - gchar *fullpath; - FolderItem *new_item; - - g_return_val_if_fail(folder != NULL, NULL); - g_return_val_if_fail(parent != NULL, NULL); - g_return_val_if_fail(name != NULL, NULL); - - path = folder_item_get_path(parent); - fs_name = g_filename_from_utf8(name, -1, NULL, NULL, NULL); - fullpath = g_strconcat(path, G_DIR_SEPARATOR_S, - fs_name ? fs_name : name, NULL); - g_free(fs_name); - g_free(path); - - if (make_dir(fullpath) < 0) { - g_free(fullpath); - return NULL; - } - - g_free(fullpath); - - if (parent->path) - path = g_strconcat(parent->path, G_DIR_SEPARATOR_S, name, - NULL); - else - path = g_strdup(name); - new_item = folder_item_new(name, path); - folder_item_append(parent, new_item); - g_free(path); - - return new_item; -} - -static gint mh_move_folder_real(Folder *folder, FolderItem *item, - FolderItem *new_parent, const gchar *name) -{ - gchar *oldpath; - gchar *newpath; - gchar *dirname; - gchar *new_dir; - gchar *name_; - gchar *utf8_name; - gchar *paths[2]; - - g_return_val_if_fail(folder != NULL, -1); - g_return_val_if_fail(item != NULL, -1); - g_return_val_if_fail(folder == item->folder, -1); - g_return_val_if_fail(item->path != NULL, -1); - g_return_val_if_fail(new_parent != NULL || name != NULL, -1); - if (new_parent) { - g_return_val_if_fail(item != new_parent, -1); - g_return_val_if_fail(item->parent != new_parent, -1); - g_return_val_if_fail(item->folder == new_parent->folder, -1); - if (g_node_is_ancestor(item->node, new_parent->node)) { - g_warning("folder to be moved is ancestor of new parent\n"); - return -1; - } - } - - oldpath = folder_item_get_path(item); - if (new_parent) { - if (name) { - name_ = g_filename_from_utf8(name, -1, NULL, NULL, - NULL); - if (!name_) - name_ = g_strdup(name); - utf8_name = g_strdup(name); - } else { - name_ = g_path_get_basename(oldpath); - utf8_name = g_filename_to_utf8(name_, -1, NULL, NULL, - NULL); - if (!utf8_name) - utf8_name = g_strdup(name_); - } - new_dir = folder_item_get_path(new_parent); - newpath = g_strconcat(new_dir, G_DIR_SEPARATOR_S, name_, NULL); - g_free(new_dir); - } else { - name_ = g_filename_from_utf8(name, -1, NULL, NULL, NULL); - utf8_name = g_strdup(name); - dirname = g_dirname(oldpath); - newpath = g_strconcat(dirname, G_DIR_SEPARATOR_S, - name_ ? name_ : name, NULL); - g_free(dirname); - } - g_free(name_); - - if (is_file_entry_exist(newpath)) { - g_warning("%s already exists\n", newpath); - g_free(oldpath); - g_free(newpath); - g_free(utf8_name); - return -1; - } - - debug_print("mh_move_folder: rename(%s, %s)\n", oldpath, newpath); - - if (g_rename(oldpath, newpath) < 0) { - FILE_OP_ERROR(oldpath, "rename"); - g_free(oldpath); - g_free(newpath); - g_free(utf8_name); - return -1; - } - - g_free(oldpath); - g_free(newpath); - - if (new_parent) { - g_node_unlink(item->node); - g_node_append(new_parent->node, item->node); - item->parent = new_parent; - if (new_parent->path != NULL) { - newpath = g_strconcat(new_parent->path, - G_DIR_SEPARATOR_S, utf8_name, - NULL); - g_free(utf8_name); - } else - newpath = utf8_name; - } else { - if (strchr(item->path, G_DIR_SEPARATOR) != NULL) { - dirname = g_dirname(item->path); - newpath = g_strconcat(dirname, G_DIR_SEPARATOR_S, - utf8_name, NULL); - g_free(dirname); - g_free(utf8_name); - } else - newpath = utf8_name; - } - - if (name) { - g_free(item->name); - item->name = g_strdup(name); - } - - paths[0] = g_strdup(item->path); - paths[1] = newpath; - g_node_traverse(item->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1, - mh_rename_folder_func, paths); - - g_free(paths[0]); - g_free(paths[1]); - - return 0; -} - -static gint mh_move_folder(Folder *folder, FolderItem *item, - FolderItem *new_parent) -{ - return mh_move_folder_real(folder, item, new_parent, NULL); -} - -static gint mh_rename_folder(Folder *folder, FolderItem *item, - const gchar *name) -{ - return mh_move_folder_real(folder, item, NULL, name); -} - -static gint mh_remove_folder(Folder *folder, FolderItem *item) -{ - gchar *path; - - g_return_val_if_fail(folder != NULL, -1); - g_return_val_if_fail(item != NULL, -1); - g_return_val_if_fail(item->path != NULL, -1); - - path = folder_item_get_path(item); - if (remove_dir_recursive(path) < 0) { - g_warning("can't remove directory `%s'\n", path); - g_free(path); - return -1; - } - - g_free(path); - folder_item_remove(item); - return 0; -} - - -static time_t mh_get_mtime(FolderItem *item) -{ - gchar *path; - struct stat s; - - path = folder_item_get_path(item); - if (g_stat(path, &s) < 0) { - FILE_OP_ERROR(path, "stat"); - return -1; - } else { - return MAX(s.st_mtime, s.st_ctime); - } -} - -static GSList *mh_get_uncached_msgs(GHashTable *msg_table, FolderItem *item) -{ - gchar *path; - DIR *dp; - struct dirent *d; - GSList *newlist = NULL; - GSList *last = NULL; - MsgInfo *msginfo; - gint n_newmsg = 0; - gint num; - - g_return_val_if_fail(item != NULL, NULL); - - path = folder_item_get_path(item); - g_return_val_if_fail(path != NULL, NULL); - if (change_dir(path) < 0) { - g_free(path); - return NULL; - } - g_free(path); - - if ((dp = opendir(".")) == NULL) { - FILE_OP_ERROR(item->path, "opendir"); - return NULL; - } - - debug_print("Searching uncached messages...\n"); - - if (msg_table) { - while ((d = readdir(dp)) != NULL) { - if ((num = to_number(d->d_name)) <= 0) continue; - - msginfo = g_hash_table_lookup - (msg_table, GUINT_TO_POINTER(num)); - - if (msginfo) { - MSG_SET_TMP_FLAGS(msginfo->flags, MSG_CACHED); - } else { - /* not found in the cache (uncached message) */ - msginfo = mh_parse_msg(d->d_name, item); - if (!msginfo) continue; - - if (!newlist) - last = newlist = - g_slist_append(NULL, msginfo); - else { - last = g_slist_append(last, msginfo); - last = last->next; - } - n_newmsg++; - } - } - } else { - /* discard all previous cache */ - while ((d = readdir(dp)) != NULL) { - if (to_number(d->d_name) <= 0) continue; - - msginfo = mh_parse_msg(d->d_name, item); - if (!msginfo) continue; - - if (!newlist) - last = newlist = g_slist_append(NULL, msginfo); - else { - last = g_slist_append(last, msginfo); - last = last->next; - } - n_newmsg++; - } - } - - closedir(dp); - - if (n_newmsg) - debug_print("%d uncached message(s) found.\n", n_newmsg); - else - debug_print("done.\n"); - - /* sort new messages in numerical order */ - if (newlist && item->sort_key == SORT_BY_NONE) { - debug_print("Sorting uncached messages in numerical order...\n"); - newlist = g_slist_sort - (newlist, (GCompareFunc)procmsg_cmp_msgnum_for_sort); - debug_print("done.\n"); - } - - return newlist; -} - -static MsgInfo *mh_parse_msg(const gchar *file, FolderItem *item) -{ - MsgInfo *msginfo; - MsgFlags flags; - - g_return_val_if_fail(item != NULL, NULL); - g_return_val_if_fail(file != NULL, NULL); - - flags.perm_flags = MSG_NEW|MSG_UNREAD; - flags.tmp_flags = 0; - - if (item->stype == F_QUEUE) { - MSG_SET_TMP_FLAGS(flags, MSG_QUEUED); - } else if (item->stype == F_DRAFT) { - MSG_SET_TMP_FLAGS(flags, MSG_DRAFT); - } - - msginfo = procheader_parse_file(file, flags, FALSE); - if (!msginfo) return NULL; - - msginfo->msgnum = atoi(file); - msginfo->folder = item; - - return msginfo; -} - -#if 0 -static gboolean mh_is_maildir_one(const gchar *path, const gchar *dir) -{ - gchar *entry; - gboolean result; - - entry = g_strconcat(path, G_DIR_SEPARATOR_S, dir, NULL); - result = is_dir_exist(entry); - g_free(entry); - - return result; -} - -/* - * check whether PATH is a Maildir style mailbox. - * This is the case if the 3 subdir: new, cur, tmp are existing. - * This functon assumes that entry is an directory - */ -static gboolean mh_is_maildir(const gchar *path) -{ - return mh_is_maildir_one(path, "new") && - mh_is_maildir_one(path, "cur") && - mh_is_maildir_one(path, "tmp"); -} -#endif - -static gboolean mh_remove_missing_folder_items_func(GNode *node, gpointer data) -{ - FolderItem *item; - gchar *path; - - g_return_val_if_fail(node->data != NULL, FALSE); - - if (G_NODE_IS_ROOT(node)) - return FALSE; - - item = FOLDER_ITEM(node->data); - - path = folder_item_get_path(item); - if (!is_dir_exist(path)) { - debug_print("folder '%s' not found. removing...\n", path); - folder_item_remove(item); - } - g_free(path); - - return FALSE; -} - -static void mh_remove_missing_folder_items(Folder *folder) -{ - g_return_if_fail(folder != NULL); - - debug_print("searching missing folders...\n"); - - g_node_traverse(folder->node, G_POST_ORDER, G_TRAVERSE_ALL, -1, - mh_remove_missing_folder_items_func, folder); -} - -static void mh_scan_tree_recursive(FolderItem *item) -{ - Folder *folder; -#ifdef G_OS_WIN32 - GDir *dir; -#else - DIR *dp; - struct dirent *d; -#endif - const gchar *dir_name; - struct stat s; - gchar *fs_path; - gchar *entry; - gchar *utf8entry; - gchar *utf8name; - gint n_msg = 0; - - g_return_if_fail(item != NULL); - g_return_if_fail(item->folder != NULL); - - folder = item->folder; - - fs_path = item->path ? - g_filename_from_utf8(item->path, -1, NULL, NULL, NULL) - : g_strdup("."); - if (!fs_path) - fs_path = g_strdup(item->path); -#ifdef G_OS_WIN32 - dir = g_dir_open(fs_path, 0, NULL); - if (!dir) { - g_warning("failed to open directory: %s\n", fs_path); - g_free(fs_path); - return; - } -#else - dp = opendir(fs_path); - if (!dp) { - FILE_OP_ERROR(fs_path, "opendir"); - g_free(fs_path); - return; - } -#endif - g_free(fs_path); - - debug_print("scanning %s ...\n", - item->path ? item->path - : LOCAL_FOLDER(item->folder)->rootpath); - if (folder->ui_func) - folder->ui_func(folder, item, folder->ui_func_data); - -#ifdef G_OS_WIN32 - while ((dir_name = g_dir_read_name(dir)) != NULL) { -#else - while ((d = readdir(dp)) != NULL) { - dir_name = d->d_name; -#endif - if (dir_name[0] == '.') continue; - - utf8name = g_filename_to_utf8(dir_name, -1, NULL, NULL, NULL); - if (!utf8name) - utf8name = g_strdup(dir_name); - - if (item->path) - utf8entry = g_strconcat(item->path, G_DIR_SEPARATOR_S, - utf8name, NULL); - else - utf8entry = g_strdup(utf8name); - entry = g_filename_from_utf8(utf8entry, -1, NULL, NULL, NULL); - if (!entry) - entry = g_strdup(utf8entry); - - if ( -#if !defined(G_OS_WIN32) && defined(HAVE_DIRENT_D_TYPE) - d->d_type == DT_DIR || - (d->d_type == DT_UNKNOWN && -#endif - g_stat(entry, &s) == 0 && S_ISDIR(s.st_mode) -#if !defined(G_OS_WIN32) && defined(HAVE_DIRENT_D_TYPE) - ) -#endif - ) { - FolderItem *new_item = NULL; - GNode *node; - -#if 0 - if (mh_is_maildir(entry)) { - g_free(entry); - g_free(utf8entry); - g_free(utf8name); - continue; - } -#endif - -#ifndef G_OS_WIN32 - if (g_utf8_validate(utf8name, -1, NULL) == FALSE) { - g_warning(_("Directory name\n" - "'%s' is not a valid UTF-8 string.\n" - "Maybe the locale encoding is used for filename.\n" - "If that is the case, you must set the following environmental variable\n" - "(see README for detail):\n" - "\n" - "\tG_FILENAME_ENCODING=@locale\n"), - utf8name); - g_free(entry); - g_free(utf8entry); - g_free(utf8name); - continue; - } -#endif /* G_OS_WIN32 */ - - node = item->node; - for (node = node->children; node != NULL; node = node->next) { - FolderItem *cur_item = FOLDER_ITEM(node->data); - if (!strcmp2(cur_item->path, utf8entry)) { - new_item = cur_item; - break; - } - } - if (!new_item) { - debug_print("new folder '%s' found.\n", entry); - new_item = folder_item_new(utf8name, utf8entry); - folder_item_append(item, new_item); - } - - if (!item->path) { - if (!folder->inbox && - !strcmp(dir_name, INBOX_DIR)) { - new_item->stype = F_INBOX; - folder->inbox = new_item; - } else if (!folder->outbox && - !strcmp(dir_name, OUTBOX_DIR)) { - new_item->stype = F_OUTBOX; - folder->outbox = new_item; - } else if (!folder->draft && - !strcmp(dir_name, DRAFT_DIR)) { - new_item->stype = F_DRAFT; - folder->draft = new_item; - } else if (!folder->queue && - !strcmp(dir_name, QUEUE_DIR)) { - new_item->stype = F_QUEUE; - folder->queue = new_item; - } else if (!folder->trash && - !strcmp(dir_name, TRASH_DIR)) { - new_item->stype = F_TRASH; - folder->trash = new_item; - } - } - - mh_scan_tree_recursive(new_item); - } else if (to_number(dir_name) > 0) n_msg++; - - g_free(entry); - g_free(utf8entry); - g_free(utf8name); - } - -#ifdef G_OS_WIN32 - g_dir_close(dir); -#else - closedir(dp); -#endif - - if (item->path) { - gint new, unread, total, min, max; - - procmsg_get_mark_sum - (item, &new, &unread, &total, &min, &max, 0); - if (n_msg > total) { - new += n_msg - total; - unread += n_msg - total; - } - item->new = new; - item->unread = unread; - item->total = n_msg; - item->updated = TRUE; - } -} - -static gboolean mh_rename_folder_func(GNode *node, gpointer data) -{ - FolderItem *item = node->data; - gchar **paths = data; - const gchar *oldpath = paths[0]; - const gchar *newpath = paths[1]; - gchar *base; - gchar *new_itempath; - gint oldpathlen; - - oldpathlen = strlen(oldpath); - if (strncmp(oldpath, item->path, oldpathlen) != 0) { - g_warning("path doesn't match: %s, %s\n", oldpath, item->path); - return TRUE; - } - - base = item->path + oldpathlen; - while (*base == G_DIR_SEPARATOR) base++; - if (*base == '\0') - new_itempath = g_strdup(newpath); - else - new_itempath = g_strconcat(newpath, G_DIR_SEPARATOR_S, base, - NULL); - g_free(item->path); - item->path = new_itempath; - - return FALSE; -} -- cgit v1.2.3