2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2001 Hiroyuki Yamamoto
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 # include <sys/time.h>
43 #include "procheader.h"
46 static GSList
*mh_get_uncached_msgs (GHashTable
*msg_table
,
48 static MsgInfo
*mh_parse_msg (const gchar
*file
,
50 static void mh_scan_tree_recursive (FolderItem
*item
);
52 static gboolean
mh_rename_folder_func (GNode
*node
,
56 GSList
*mh_get_msg_list(Folder
*folder
, FolderItem
*item
, gboolean use_cache
)
59 GHashTable
*msg_table
;
62 gboolean scan_new
= TRUE
;
64 struct timeval tv_before
, tv_after
, tv_result
;
66 gettimeofday(&tv_before
, NULL
);
69 g_return_val_if_fail(item
!= NULL
, NULL
);
71 path
= folder_item_get_path(item
);
72 if (stat(path
, &s
) < 0) {
73 FILE_OP_ERROR(path
, "stat");
75 if (item
->mtime
== s
.st_mtime
) {
76 debug_print("Folder is not modified.\n");
79 item
->mtime
= s
.st_mtime
;
83 if (use_cache
&& !scan_new
) {
84 mlist
= procmsg_read_cache(item
, FALSE
);
86 mlist
= mh_get_uncached_msgs(NULL
, item
);
87 } else if (use_cache
) {
90 mlist
= procmsg_read_cache(item
, TRUE
);
91 msg_table
= procmsg_msg_hash_table_create(mlist
);
93 newlist
= mh_get_uncached_msgs(msg_table
, item
);
95 g_hash_table_destroy(msg_table
);
97 mlist
= g_slist_concat(mlist
, newlist
);
99 mlist
= mh_get_uncached_msgs(NULL
, item
);
101 procmsg_set_flags(mlist
, item
);
104 gettimeofday(&tv_after
, NULL
);
106 timersub(&tv_after
, &tv_before
, &tv_result
);
107 g_print("mh_get_msg_list: %s: elapsed time: %ld.%06ld sec\n",
108 item
->path
, tv_result
.tv_sec
, tv_result
.tv_usec
);
114 gchar
*mh_fetch_msg(Folder
*folder
, FolderItem
*item
, gint num
)
119 g_return_val_if_fail(item
!= NULL
, NULL
);
120 g_return_val_if_fail(num
> 0 && num
<= item
->last_num
, NULL
);
122 path
= folder_item_get_path(item
);
123 file
= g_strconcat(path
, G_DIR_SEPARATOR_S
, itos(num
), NULL
);
125 if (!is_file_exist(file
)) {
133 gint
mh_add_msg(Folder
*folder
, FolderItem
*dest
, const gchar
*file
,
134 gboolean remove_source
)
139 g_return_val_if_fail(dest
!= NULL
, -1);
140 g_return_val_if_fail(file
!= NULL
, -1);
142 if (dest
->last_num
< 0) {
143 mh_scan_folder(folder
, dest
);
144 if (dest
->last_num
< 0) return -1;
147 destpath
= folder_item_get_path(dest
);
148 g_return_val_if_fail(destpath
!= NULL
, -1);
149 if (!is_dir_exist(destpath
))
150 make_dir_hier(destpath
);
152 destfile
= g_strdup_printf("%s%c%d", destpath
, G_DIR_SEPARATOR
,
155 if (link(file
, destfile
) < 0) {
156 if (EXDEV
== errno
) {
157 if (copy_file(file
, destfile
) < 0) {
158 g_warning(_("can't copy message %s to %s\n"),
164 FILE_OP_ERROR(file
, "link");
171 if (unlink(file
) < 0)
172 FILE_OP_ERROR(file
, "unlink");
177 return dest
->last_num
;
180 gint
mh_move_msg(Folder
*folder
, FolderItem
*dest
, MsgInfo
*msginfo
)
187 PrefsFolderItem
*prefs
;
189 g_return_val_if_fail(dest
!= NULL
, -1);
190 g_return_val_if_fail(msginfo
!= NULL
, -1);
192 if (msginfo
->folder
== dest
) {
193 g_warning(_("the src folder is identical to the dest.\n"));
197 if (dest
->last_num
< 0) {
198 mh_scan_folder(folder
, dest
);
199 if (dest
->last_num
< 0) return -1;
204 destdir
= folder_item_get_path(dest
);
205 if ((fp
= procmsg_open_mark_file(destdir
, TRUE
)) == NULL
)
206 g_warning(_("Can't open mark file.\n"));
208 debug_print(_("Moving message %s%c%d to %s ...\n"),
209 msginfo
->folder
->path
, G_DIR_SEPARATOR
,
210 msginfo
->msgnum
, dest
->path
);
211 srcfile
= procmsg_get_message_file_path(msginfo
);
212 destfile
= g_strdup_printf("%s%c%d", destdir
, G_DIR_SEPARATOR
,
216 if (move_file(srcfile
, destfile
) < 0) {
223 if (prefs
&& prefs
->enable_folder_chmod
&& prefs
->folder_chmod
) {
224 if (chmod(destfile
, prefs
->folder_chmod
) < 0)
225 FILE_OP_ERROR(destfile
, "chmod");
228 filemode
= prefs
->folder_chmod
;
229 if (filemode
& S_IRGRP
) filemode
|= S_IWGRP
;
230 if (filemode
& S_IROTH
) filemode
|= S_IWOTH
;
240 newmsginfo
.msgnum
= dest
->last_num
;
241 newmsginfo
.flags
= msginfo
->flags
;
242 if (dest
->stype
== F_OUTBOX
||
243 dest
->stype
== F_QUEUE
||
244 dest
->stype
== F_DRAFT
||
245 dest
->stype
== F_TRASH
)
246 MSG_UNSET_PERM_FLAGS(newmsginfo
.flags
,
247 MSG_NEW
|MSG_UNREAD
|MSG_DELETED
);
249 procmsg_write_flags(&newmsginfo
, fp
);
253 fchmod(fileno(fp
), filemode
);
255 markfile
= folder_item_get_mark_file(dest
);
257 chmod(markfile
, filemode
);
266 return dest
->last_num
;
269 gint
mh_move_msgs_with_dest(Folder
*folder
, FolderItem
*dest
, GSList
*msglist
)
277 PrefsFolderItem
*prefs
;
279 g_return_val_if_fail(dest
!= NULL
, -1);
280 g_return_val_if_fail(msglist
!= NULL
, -1);
282 if (dest
->last_num
< 0) {
283 mh_scan_folder(folder
, dest
);
284 if (dest
->last_num
< 0) return -1;
289 destdir
= folder_item_get_path(dest
);
290 if ((fp
= procmsg_open_mark_file(destdir
, TRUE
)) == NULL
)
291 g_warning(_("Can't open mark file.\n"));
293 for (cur
= msglist
; cur
!= NULL
; cur
= cur
->next
) {
294 msginfo
= (MsgInfo
*)cur
->data
;
296 if (msginfo
->folder
== dest
) {
297 g_warning(_("the src folder is identical to the dest.\n"));
300 debug_print(_("Moving message %s%c%d to %s ...\n"),
301 msginfo
->folder
->path
, G_DIR_SEPARATOR
,
302 msginfo
->msgnum
, dest
->path
);
304 srcfile
= procmsg_get_message_file_path(msginfo
);
305 destfile
= g_strdup_printf("%s%c%d", destdir
, G_DIR_SEPARATOR
,
308 if (move_file(srcfile
, destfile
) < 0) {
321 newmsginfo
.msgnum
= dest
->last_num
;
322 newmsginfo
.flags
= msginfo
->flags
;
323 if (dest
->stype
== F_OUTBOX
||
324 dest
->stype
== F_QUEUE
||
325 dest
->stype
== F_DRAFT
||
326 dest
->stype
== F_TRASH
)
329 MSG_NEW
|MSG_UNREAD
|MSG_DELETED
);
331 procmsg_write_flags(&newmsginfo
, fp
);
338 return dest
->last_num
;
341 gint
mh_copy_msg(Folder
*folder
, FolderItem
*dest
, MsgInfo
*msginfo
)
348 PrefsFolderItem
*prefs
;
350 g_return_val_if_fail(dest
!= NULL
, -1);
351 g_return_val_if_fail(msginfo
!= NULL
, -1);
353 if (msginfo
->folder
== dest
) {
354 g_warning(_("the src folder is identical to the dest.\n"));
358 if (dest
->last_num
< 0) {
359 mh_scan_folder(folder
, dest
);
360 if (dest
->last_num
< 0) return -1;
365 destdir
= folder_item_get_path(dest
);
366 if (!is_dir_exist(destdir
))
367 make_dir_hier(destdir
);
369 if ((fp
= procmsg_open_mark_file(destdir
, TRUE
)) == NULL
)
370 g_warning(_("Can't open mark file.\n"));
372 debug_print(_("Copying message %s%c%d to %s ...\n"),
373 msginfo
->folder
->path
, G_DIR_SEPARATOR
,
374 msginfo
->msgnum
, dest
->path
);
375 srcfile
= procmsg_get_message_file_path(msginfo
);
376 destfile
= g_strdup_printf("%s%c%d", destdir
, G_DIR_SEPARATOR
,
382 if (is_file_exist(destfile
)) {
383 g_warning(_("%s already exists."), destfile
);
390 if (copy_file(srcfile
, destfile
) < 0) {
391 FILE_OP_ERROR(srcfile
, "copy");
398 if (prefs
&& prefs
->enable_folder_chmod
&& prefs
->folder_chmod
) {
399 if (chmod(destfile
, prefs
->folder_chmod
) < 0)
400 FILE_OP_ERROR(destfile
, "chmod");
403 filemode
= prefs
->folder_chmod
;
404 if (filemode
& S_IRGRP
) filemode
|= S_IWGRP
;
405 if (filemode
& S_IROTH
) filemode
|= S_IWOTH
;
415 newmsginfo
.msgnum
= dest
->last_num
;
416 newmsginfo
.flags
= msginfo
->flags
;
417 if (dest
->stype
== F_OUTBOX
||
418 dest
->stype
== F_QUEUE
||
419 dest
->stype
== F_DRAFT
||
420 dest
->stype
== F_TRASH
)
421 MSG_UNSET_PERM_FLAGS(newmsginfo
.flags
,
422 MSG_NEW
|MSG_UNREAD
|MSG_DELETED
);
423 procmsg_write_flags(&newmsginfo
, fp
);
427 fchmod(fileno(fp
), filemode
);
429 markfile
= folder_item_get_mark_file(dest
);
431 chmod(markfile
, filemode
);
440 return dest
->last_num
;
444 gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
452 src_folder = msginfo->folder->folder;
454 g_return_val_if_fail(src_folder->fetch_msg != NULL, -1);
456 filename = src_folder->fetch_msg(src_folder,
459 if (filename == NULL)
462 num = folder->add_msg(folder, dest, filename, FALSE);
464 destdir = folder_item_get_path(dest);
465 if ((fp = procmsg_open_mark_file(destdir, TRUE)) == NULL)
466 g_warning(_("Can't open mark file.\n"));
471 newmsginfo.msgnum = dest->last_num;
472 newmsginfo.flags = msginfo->flags;
473 if (dest->stype == F_OUTBOX ||
474 dest->stype == F_QUEUE ||
475 dest->stype == F_DRAFT ||
476 dest->stype == F_TRASH)
477 MSG_UNSET_FLAGS(newmsginfo.flags,
478 MSG_NEW|MSG_UNREAD|MSG_DELETED);
480 procmsg_write_flags(&newmsginfo, fp);
488 gint
mh_copy_msgs_with_dest(Folder
*folder
, FolderItem
*dest
, GSList
*msglist
)
497 g_return_val_if_fail(dest
!= NULL
, -1);
498 g_return_val_if_fail(msglist
!= NULL
, -1);
500 if (dest
->last_num
< 0) {
501 mh_scan_folder(folder
, dest
);
502 if (dest
->last_num
< 0) return -1;
505 destdir
= folder_item_get_path(dest
);
506 if (!is_dir_exist(destdir
))
507 make_dir_hier(destdir
);
509 if ((fp
= procmsg_open_mark_file(destdir
, TRUE
)) == NULL
)
510 g_warning(_("Can't open mark file.\n"));
512 for (cur
= msglist
; cur
!= NULL
; cur
= cur
->next
) {
513 msginfo
= (MsgInfo
*)cur
->data
;
515 if (msginfo
->folder
== dest
) {
516 g_warning(_("the src folder is identical to the dest.\n"));
519 debug_print(_("Copying message %s%c%d to %s ...\n"),
520 msginfo
->folder
->path
, G_DIR_SEPARATOR
,
521 msginfo
->msgnum
, dest
->path
);
523 srcfile
= procmsg_get_message_file_path(msginfo
);
524 destfile
= g_strdup_printf("%s%c%d", destdir
, G_DIR_SEPARATOR
,
527 if (is_file_exist(destfile
)) {
528 g_warning(_("%s already exists."), destfile
);
534 if (copy_file(srcfile
, destfile
) < 0) {
535 FILE_OP_ERROR(srcfile
, "copy");
548 newmsginfo
.msgnum
= dest
->last_num
;
549 newmsginfo
.flags
= msginfo
->flags
;
550 if (dest
->stype
== F_OUTBOX
||
551 dest
->stype
== F_QUEUE
||
552 dest
->stype
== F_DRAFT
||
553 dest
->stype
== F_TRASH
)
556 MSG_NEW
|MSG_UNREAD
|MSG_DELETED
);
557 procmsg_write_flags(&newmsginfo
, fp
);
564 return dest
->last_num
;
567 gint
mh_remove_msg(Folder
*folder
, FolderItem
*item
, gint num
)
571 g_return_val_if_fail(item
!= NULL
, -1);
573 file
= mh_fetch_msg(folder
, item
, num
);
574 g_return_val_if_fail(file
!= NULL
, -1);
576 if (unlink(file
) < 0) {
577 FILE_OP_ERROR(file
, "unlink");
586 gint
mh_remove_all_msg(Folder
*folder
, FolderItem
*item
)
591 g_return_val_if_fail(item
!= NULL
, -1);
593 path
= folder_item_get_path(item
);
594 g_return_val_if_fail(path
!= NULL
, -1);
595 val
= remove_all_numbered_files(path
);
601 gboolean
mh_is_msg_changed(Folder
*folder
, FolderItem
*item
, MsgInfo
*msginfo
)
605 if (stat(itos(msginfo
->msgnum
), &s
) < 0 ||
606 msginfo
->size
!= s
.st_size
||
607 msginfo
->mtime
!= s
.st_mtime
)
613 void mh_scan_folder(Folder
*folder
, FolderItem
*item
)
623 g_return_if_fail(item
!= NULL
);
625 path
= folder_item_get_path(item
);
626 g_return_if_fail(path
!= NULL
);
627 if (change_dir(path
) < 0) {
633 if ((dp
= opendir(".")) == NULL
) {
634 FILE_OP_ERROR(item
->path
, "opendir");
639 folder
->ui_func(folder
, item
, folder
->ui_func_data
);
641 while ((d
= readdir(dp
)) != NULL
) {
642 if ((num
= to_number(d
->d_name
)) >= 0 &&
643 stat(d
->d_name
, &s
) == 0 &&
644 S_ISREG(s
.st_mode
)) {
654 item
->new = item
->unread
= item
->total
= 0;
656 gint
new, unread
, total
;
658 procmsg_get_mark_sum(".", &new, &unread
, &total
);
660 new += n_msg
- total
;
661 unread
+= n_msg
- total
;
664 item
->unread
= unread
;
668 debug_print(_("Last number in dir %s = %d\n"), item
->path
, max
);
669 item
->last_num
= max
;
672 void mh_scan_tree(Folder
*folder
)
677 g_return_if_fail(folder
!= NULL
);
679 folder_tree_destroy(folder
);
680 item
= folder_item_new(folder
->name
, NULL
);
681 item
->folder
= folder
;
682 folder
->node
= g_node_new(item
);
684 rootpath
= folder_item_get_path(item
);
685 if (change_dir(rootpath
) < 0) {
691 mh_scan_tree_recursive(item
);
694 #define MAKE_DIR_IF_NOT_EXIST(dir) \
696 if (!is_dir_exist(dir)) { \
697 if (is_file_exist(dir)) { \
698 g_warning(_("File `%s' already exists.\n" \
699 "Can't create folder."), dir); \
702 if (mkdir(dir, S_IRWXU) < 0) { \
703 FILE_OP_ERROR(dir, "mkdir"); \
706 if (chmod(dir, S_IRWXU) < 0) \
707 FILE_OP_ERROR(dir, "chmod"); \
711 gint
mh_create_tree(Folder
*folder
)
715 g_return_val_if_fail(folder
!= NULL
, -1);
717 CHDIR_RETURN_VAL_IF_FAIL(get_home_dir(), -1);
718 rootpath
= LOCAL_FOLDER(folder
)->rootpath
;
719 MAKE_DIR_IF_NOT_EXIST(rootpath
);
720 CHDIR_RETURN_VAL_IF_FAIL(rootpath
, -1);
721 MAKE_DIR_IF_NOT_EXIST(INBOX_DIR
);
722 MAKE_DIR_IF_NOT_EXIST(OUTBOX_DIR
);
723 MAKE_DIR_IF_NOT_EXIST(QUEUE_DIR
);
724 MAKE_DIR_IF_NOT_EXIST(DRAFT_DIR
);
725 MAKE_DIR_IF_NOT_EXIST(TRASH_DIR
);
730 #undef MAKE_DIR_IF_NOT_EXIST
732 FolderItem
*mh_create_folder(Folder
*folder
, FolderItem
*parent
,
737 FolderItem
*new_item
;
739 g_return_val_if_fail(folder
!= NULL
, NULL
);
740 g_return_val_if_fail(parent
!= NULL
, NULL
);
741 g_return_val_if_fail(name
!= NULL
, NULL
);
743 path
= folder_item_get_path(parent
);
744 if (!is_dir_exist(path
))
747 fullpath
= g_strconcat(path
, G_DIR_SEPARATOR_S
, name
, NULL
);
750 if (mkdir(fullpath
, S_IRWXU
) < 0) {
751 FILE_OP_ERROR(fullpath
, "mkdir");
755 if (chmod(fullpath
, S_IRWXU
) < 0)
756 FILE_OP_ERROR(fullpath
, "chmod");
761 path
= g_strconcat(parent
->path
, G_DIR_SEPARATOR_S
, name
,
764 path
= g_strdup(name
);
765 new_item
= folder_item_new(name
, path
);
766 folder_item_append(parent
, new_item
);
772 gint
mh_rename_folder(Folder
*folder
, FolderItem
*item
, const gchar
*name
)
780 g_return_val_if_fail(folder
!= NULL
, -1);
781 g_return_val_if_fail(item
!= NULL
, -1);
782 g_return_val_if_fail(item
->path
!= NULL
, -1);
783 g_return_val_if_fail(name
!= NULL
, -1);
785 oldpath
= folder_item_get_path(item
);
786 if (!is_dir_exist(oldpath
))
787 make_dir_hier(oldpath
);
789 dirname
= g_dirname(oldpath
);
790 newpath
= g_strconcat(dirname
, G_DIR_SEPARATOR_S
, name
, NULL
);
793 if (rename(oldpath
, newpath
) < 0) {
794 FILE_OP_ERROR(oldpath
, "rename");
803 if (strchr(item
->path
, G_DIR_SEPARATOR
) != NULL
) {
804 dirname
= g_dirname(item
->path
);
805 newpath
= g_strconcat(dirname
, G_DIR_SEPARATOR_S
, name
, NULL
);
808 newpath
= g_strdup(name
);
811 item
->name
= g_strdup(name
);
813 node
= g_node_find(item
->folder
->node
, G_PRE_ORDER
, G_TRAVERSE_ALL
,
815 paths
[0] = g_strdup(item
->path
);
817 g_node_traverse(node
, G_PRE_ORDER
, G_TRAVERSE_ALL
, -1,
818 mh_rename_folder_func
, paths
);
825 gint
mh_remove_folder(Folder
*folder
, FolderItem
*item
)
829 g_return_val_if_fail(folder
!= NULL
, -1);
830 g_return_val_if_fail(item
!= NULL
, -1);
831 g_return_val_if_fail(item
->path
!= NULL
, -1);
833 path
= folder_item_get_path(item
);
834 if (remove_dir_recursive(path
) < 0) {
835 g_warning("can't remove directory `%s'\n", path
);
841 folder_item_remove(item
);
846 static GSList
*mh_get_uncached_msgs(GHashTable
*msg_table
, FolderItem
*item
)
852 GSList
*newlist
= NULL
;
858 g_return_val_if_fail(item
!= NULL
, NULL
);
860 path
= folder_item_get_path(item
);
861 g_return_val_if_fail(path
!= NULL
, NULL
);
862 if (change_dir(path
) < 0) {
868 if ((dp
= opendir(".")) == NULL
) {
869 FILE_OP_ERROR(item
->path
, "opendir");
873 debug_print(_("\tSearching uncached messages... "));
876 while ((d
= readdir(dp
)) != NULL
) {
877 if ((num
= to_number(d
->d_name
)) < 0) continue;
878 if (stat(d
->d_name
, &s
) < 0) {
879 FILE_OP_ERROR(d
->d_name
, "stat");
882 if (!S_ISREG(s
.st_mode
)) continue;
884 msginfo
= g_hash_table_lookup
885 (msg_table
, GUINT_TO_POINTER(num
));
888 /* not found in the cache (uncached message) */
889 msginfo
= mh_parse_msg(d
->d_name
, item
);
890 if (!msginfo
) continue;
894 g_slist_append(NULL
, msginfo
);
896 last
= g_slist_append(last
, msginfo
);
903 /* discard all previous cache */
904 while ((d
= readdir(dp
)) != NULL
) {
905 if (to_number(d
->d_name
) < 0) continue;
906 if (stat(d
->d_name
, &s
) < 0) {
907 FILE_OP_ERROR(d
->d_name
, "stat");
910 if (!S_ISREG(s
.st_mode
)) continue;
912 msginfo
= mh_parse_msg(d
->d_name
, item
);
913 if (!msginfo
) continue;
916 last
= newlist
= g_slist_append(NULL
, msginfo
);
918 last
= g_slist_append(last
, msginfo
);
928 debug_print(_("%d uncached message(s) found.\n"), n_newmsg
);
930 debug_print(_("done.\n"));
932 /* sort new messages in numerical order */
934 debug_print(_("\tSorting uncached messages in numerical order... "));
935 newlist
= g_slist_sort
936 (newlist
, (GCompareFunc
)procmsg_cmp_msgnum_for_sort
);
937 debug_print(_("done.\n"));
943 static MsgInfo
*mh_parse_msg(const gchar
*file
, FolderItem
*item
)
949 flags
.perm_flags
= MSG_NEW
|MSG_UNREAD
;
952 g_return_val_if_fail(item
!= NULL
, NULL
);
953 g_return_val_if_fail(file
!= NULL
, NULL
);
955 if (item
->stype
== F_QUEUE
) {
956 MSG_SET_TMP_FLAGS(flags
, MSG_QUEUED
);
957 } else if (item
->stype
== F_DRAFT
) {
958 MSG_SET_TMP_FLAGS(flags
, MSG_DRAFT
);
961 msginfo
= procheader_parse(file
, flags
, FALSE
);
962 if (!msginfo
) return NULL
;
964 msginfo
->msgnum
= atoi(file
);
965 msginfo
->folder
= item
;
967 if (stat(file
, &s
) < 0) {
968 FILE_OP_ERROR(file
, "stat");
972 msginfo
->size
= s
.st_size
;
973 msginfo
->mtime
= s
.st_mtime
;
979 static gboolean
mh_is_maildir_one(const gchar
*path
, const gchar
*dir
)
984 entry
= g_strconcat(path
, G_DIR_SEPARATOR_S
, dir
, NULL
);
985 result
= is_dir_exist(entry
);
992 * check whether PATH is a Maildir style mailbox.
993 * This is the case if the 3 subdir: new, cur, tmp are existing.
994 * This functon assumes that entry is an directory
996 static gboolean
mh_is_maildir(const gchar
*path
)
998 return mh_is_maildir_one(path
, "new") &&
999 mh_is_maildir_one(path
, "cur") &&
1000 mh_is_maildir_one(path
, "tmp");
1003 static void mh_scan_tree_recursive(FolderItem
*item
)
1011 g_return_if_fail(item
!= NULL
);
1012 g_return_if_fail(item
->folder
!= NULL
);
1014 dp
= opendir(item
->path
? item
->path
: ".");
1016 FILE_OP_ERROR(item
->path
? item
->path
: ".", "opendir");
1020 debug_print("scanning %s ...\n",
1021 item
->path
? item
->path
1022 : LOCAL_FOLDER(item
->folder
)->rootpath
);
1023 if (item
->folder
->ui_func
)
1024 item
->folder
->ui_func(item
->folder
, item
,
1025 item
->folder
->ui_func_data
);
1027 while ((d
= readdir(dp
)) != NULL
) {
1028 if (d
->d_name
[0] == '.') continue;
1031 entry
= g_strconcat(item
->path
, G_DIR_SEPARATOR_S
,
1034 entry
= g_strdup(d
->d_name
);
1036 if (stat(entry
, &s
) < 0) {
1037 FILE_OP_ERROR(entry
, "stat");
1042 if (S_ISDIR(s
.st_mode
)) {
1043 FolderItem
*new_item
;
1045 if (mh_is_maildir(entry
)) {
1050 new_item
= folder_item_new(d
->d_name
, entry
);
1051 folder_item_append(item
, new_item
);
1053 if (!strcmp(d
->d_name
, "inbox")) {
1054 new_item
->stype
= F_INBOX
;
1055 item
->folder
->inbox
= new_item
;
1056 } else if (!strcmp(d
->d_name
, "outbox")) {
1057 new_item
->stype
= F_OUTBOX
;
1058 item
->folder
->outbox
= new_item
;
1059 } else if (!strcmp(d
->d_name
, "draft")) {
1060 new_item
->stype
= F_DRAFT
;
1061 item
->folder
->draft
= new_item
;
1062 } else if (!strcmp(d
->d_name
, "queue")) {
1063 new_item
->stype
= F_QUEUE
;
1064 item
->folder
->queue
= new_item
;
1065 } else if (!strcmp(d
->d_name
, "trash")) {
1066 new_item
->stype
= F_TRASH
;
1067 item
->folder
->trash
= new_item
;
1070 mh_scan_tree_recursive(new_item
);
1071 } else if (to_number(d
->d_name
) != -1) n_msg
++;
1079 gint
new, unread
, total
;
1081 procmsg_get_mark_sum(item
->path
, &new, &unread
, &total
);
1082 if (n_msg
> total
) {
1083 new += n_msg
- total
;
1084 unread
+= n_msg
- total
;
1087 item
->unread
= unread
;
1088 item
->total
= n_msg
;
1092 static gboolean
mh_rename_folder_func(GNode
*node
, gpointer data
)
1094 FolderItem
*item
= node
->data
;
1095 gchar
**paths
= data
;
1096 const gchar
*oldpath
= paths
[0];
1097 const gchar
*newpath
= paths
[1];
1099 gchar
*new_itempath
;
1102 oldpathlen
= strlen(oldpath
);
1103 if (strncmp(oldpath
, item
->path
, oldpathlen
) != 0) {
1104 g_warning("path doesn't match: %s, %s\n", oldpath
, item
->path
);
1108 base
= item
->path
+ oldpathlen
;
1109 while (*base
== G_DIR_SEPARATOR
) base
++;
1111 new_itempath
= g_strdup(newpath
);
1113 new_itempath
= g_strconcat(newpath
, G_DIR_SEPARATOR_S
, base
,
1116 item
->path
= new_itempath
;