/*
* Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2012 Hiroyuki Yamamoto and the Claws Mail team
+ * Copyright (C) 1999-2013 Hiroyuki Yamamoto and the Claws Mail 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
#include <time.h>
#include "folder.h"
+#include "folder_item_prefs.h"
#include "mh.h"
#include "procmsg.h"
#include "procheader.h"
#include "statusbar.h"
#include "gtkutils.h"
#include "timing.h"
+#include "msgcache.h"
/* Define possible missing constants for Windows. */
#ifdef G_OS_WIN32
mh_class.type = F_MH;
mh_class.idstr = "mh";
mh_class.uistr = "MH";
+ mh_class.supports_server_search = FALSE;
/* Folder functions */
mh_class.new_folder = mh_folder_new;
mh_class.add_msgs = mh_add_msgs;
mh_class.copy_msg = mh_copy_msg;
mh_class.copy_msgs = mh_copy_msgs;
+ mh_class.search_msgs = folder_item_search_msgs_local;
mh_class.remove_msg = mh_remove_msg;
mh_class.remove_msgs = mh_remove_msgs;
mh_class.remove_all_msg = mh_remove_all_msg;
gboolean mh_scan_required(Folder *folder, FolderItem *item)
{
gchar *path;
- struct stat s;
+ GStatBuf s;
path = folder_item_get_path(item);
cm_return_val_if_fail(path != NULL, FALSE);
static void mh_get_last_num(Folder *folder, FolderItem *item)
{
- gchar *path;
- DIR *dp;
- struct dirent *d;
+ gchar *path, *fullpath;
+ GDir *dp;
+ const gchar *d;
+ GError *error = NULL;
gint max = 0;
gint num;
path = folder_item_get_path(item);
cm_return_if_fail(path != NULL);
- if (change_dir(path) < 0) {
- g_free(path);
- return;
- }
- g_free(path);
- if ((dp = opendir(".")) == NULL) {
- FILE_OP_ERROR(item->path, "opendir");
+ if ((dp = g_dir_open(path, 0, &error)) == NULL) {
+ g_message("Couldn't open current directory: %s (%d).\n",
+ error->message, error->code);
+ g_error_free(error);
+ g_free(path);
return;
}
- while ((d = readdir(dp)) != NULL) {
- if ((num = to_number(d->d_name)) > 0 &&
- dirent_is_regular_file(d)) {
+ while ((d = g_dir_read_name(dp)) != NULL) {
+ fullpath = g_strconcat(path, G_DIR_SEPARATOR_S, d, NULL);
+ if ((num = to_number(d)) > 0 &&
+ g_file_test(fullpath, G_FILE_TEST_IS_REGULAR)) {
if (max < num)
max = num;
}
+ g_free(fullpath);
+
if (num % 2000 == 0)
GTK_EVENTS_FLUSH();
}
- closedir(dp);
+ g_dir_close(dp);
+ g_free(path);
debug_print("Last number in dir %s = %d\n", item->path?item->path:"(null)", max);
item->last_num = max;
{
gchar *path;
- DIR *dp;
- struct dirent *d;
+ GDir *dp;
+ const gchar *d;
+ GError *error = NULL;
gint num, nummsgs = 0;
cm_return_val_if_fail(item != NULL, -1);
path = folder_item_get_path(item);
cm_return_val_if_fail(path != NULL, -1);
- if (change_dir(path) < 0) {
+
+ if ((dp = g_dir_open(path, 0, &error)) == NULL) {
+ g_message("Couldn't open current directory: %s (%d).\n",
+ error->message, error->code);
+ g_error_free(error);
g_free(path);
return -1;
}
g_free(path);
- if ((dp = opendir(".")) == NULL) {
- FILE_OP_ERROR(item->path, "opendir");
- return -1;
- }
-
- while ((d = readdir(dp)) != NULL) {
- if ((num = to_number(d->d_name)) > 0) {
+ while ((d = g_dir_read_name(dp)) != NULL) {
+ if ((num = to_number(d)) > 0) {
*list = g_slist_prepend(*list, GINT_TO_POINTER(num));
nummsgs++;
}
}
- closedir(dp);
+ g_dir_close(dp);
mh_set_mtime(folder, item);
return nummsgs;
destpath = folder_item_get_path(dest);
cm_return_val_if_fail(destpath != NULL, NULL);
+ if (dest->last_num < 0) {
+ mh_get_last_num(dest->folder, dest);
+ if (dest->last_num < 0) return NULL;
+ }
+
if (!is_dir_exist(destpath))
make_dir_hier(destpath);
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"),
+ g_warning("can't copy message %s to %s",
fileinfo->file, destfile);
g_free(destfile);
return -1;
FolderItem *src = NULL;
gchar *srcfile;
gchar *destfile;
- gint filemode = 0;
FolderItemPrefs *prefs;
MsgInfo *msginfo = NULL;
MsgInfoList *cur = NULL;
cm_return_val_if_fail(msginfo != NULL, -1);
if (msginfo->folder == dest) {
- g_warning("the src folder is identical to the dest.\n");
+ g_warning("the src folder is identical to the dest.");
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;
}
if (relation) {
if (g_hash_table_lookup(relation, msginfo) != NULL)
- g_warning("already in : %p", msginfo);
+ g_warning("already in: %p", msginfo);
g_hash_table_insert(relation, msginfo, GINT_TO_POINTER(dest->last_num+1));
}
static gboolean mh_is_msg_changed(Folder *folder, FolderItem *item,
MsgInfo *msginfo)
{
- struct stat s;
+ GStatBuf s;
+ gchar *path;
- if (g_stat(itos(msginfo->msgnum), &s) < 0 ||
+ path = g_strdup_printf("%s%c%d", folder_item_get_path(item),
+ G_DIR_SEPARATOR, msginfo->msgnum);
+ if (g_stat((path), &s) < 0 ||
msginfo->size != s.st_size || (
(msginfo->mtime - s.st_mtime != 0) &&
(msginfo->mtime - s.st_mtime != 3600) &&
- (msginfo->mtime - s.st_mtime != -3600)))
+ (msginfo->mtime - s.st_mtime != -3600))) {
+ g_free(path);
return TRUE;
+ }
+ g_free(path);
return FALSE;
}
static gint mh_scan_tree(Folder *folder)
{
FolderItem *item;
- gchar *rootpath;
cm_return_val_if_fail(folder != NULL, -1);
} 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);
{ \
if (!is_dir_exist(dir)) { \
if (is_file_exist(dir)) { \
- g_warning("File `%s' already exists.\n" \
+ g_warning("File '%s' already exists. " \
"Can't create folder.", dir); \
return -1; \
} \
if (make_dir_hier(dir) < 0) \
return -1; \
+ debug_print("Created dir '%s'\n", dir); \
} \
}
static gint mh_create_tree(Folder *folder)
{
- gchar *rootpath, *f;
+ gchar *rootpath, *f, *path;
cm_return_val_if_fail(folder != NULL, -1);
- CHDIR_RETURN_VAL_IF_FAIL(get_mail_base_dir(), -1);
rootpath = LOCAL_FOLDER(folder)->rootpath;
+#ifdef G_OS_UNIX
+ if (*rootpath == '/') {
+#elif defined G_OS_WIN32
+ if (g_ascii_isalpha(*rootpath) && !strncmp(rootpath + 1, "\:", 2)) {
+#endif
+ /* Folder path is absolute. */
+ rootpath = g_strdup(rootpath);
+ } else {
+ /* Folder path is relative, using mail base dir. */
+ rootpath = g_strconcat(get_mail_base_dir(), G_DIR_SEPARATOR_S,
+ rootpath, NULL);
+ }
+
MAKE_DIR_IF_NOT_EXIST(rootpath);
- CHDIR_RETURN_VAL_IF_FAIL(rootpath, -1);
/* Create special directories as needed */
if (folder->inbox != NULL &&
f = folder->inbox->path;
else
f = INBOX_DIR;
- MAKE_DIR_IF_NOT_EXIST(f);
+ path = g_strconcat(rootpath, G_DIR_SEPARATOR_S, f, NULL);
+ MAKE_DIR_IF_NOT_EXIST(path);
+ g_free(path);
if (folder->outbox != NULL &&
folder->outbox->path != NULL)
f = folder->outbox->path;
else
f = OUTBOX_DIR;
- MAKE_DIR_IF_NOT_EXIST(f);
+ path = g_strconcat(rootpath, G_DIR_SEPARATOR_S, f, NULL);
+ MAKE_DIR_IF_NOT_EXIST(path);
+ g_free(path);
if (folder->draft != NULL &&
folder->draft->path != NULL)
f = folder->draft->path;
else
f = DRAFT_DIR;
- MAKE_DIR_IF_NOT_EXIST(f);
+ path = g_strconcat(rootpath, G_DIR_SEPARATOR_S, f, NULL);
+ MAKE_DIR_IF_NOT_EXIST(path);
+ g_free(path);
if (folder->queue != NULL &&
folder->queue->path != NULL)
f = folder->queue->path;
else
f = QUEUE_DIR;
- MAKE_DIR_IF_NOT_EXIST(f);
+ path = g_strconcat(rootpath, G_DIR_SEPARATOR_S, f, NULL);
+ MAKE_DIR_IF_NOT_EXIST(path);
+ g_free(path);
if (folder->trash != NULL &&
folder->trash->path != NULL)
f = folder->trash->path;
else
f = TRASH_DIR;
- MAKE_DIR_IF_NOT_EXIST(f);
+ path = g_strconcat(rootpath, G_DIR_SEPARATOR_S, f, NULL);
+ MAKE_DIR_IF_NOT_EXIST(path);
+ g_free(path);
+ g_free(rootpath);
return 0;
}
if (!is_dir_exist(real_path) && is_dir_exist(path)) {
/* mmh, older version did put utf8 filenames instead of
* the correct encoding */
- g_rename(path, real_path);
- folder_item_scan(item);
+ if (g_rename(path, real_path) == 0)
+ folder_item_scan(item);
}
g_free(path);
return real_path;
}
+static gboolean mh_renumber_msg(MsgInfo *info)
+{
+ gchar *src, *dest;
+ gboolean result = FALSE;
+ guint num;
+ cm_return_val_if_fail(info != NULL, FALSE);
+
+ src = folder_item_fetch_msg(info->folder, info->msgnum);
+ dest = mh_get_new_msg_filename(info->folder);
+ num = info->folder->last_num + 1;
+
+ if (move_file(src, dest, FALSE) == 0) {
+ msgcache_remove_msg(info->folder->cache, info->msgnum);
+ info->msgnum = num;
+ msgcache_add_msg(info->folder->cache, info);
+ result = TRUE;
+ }
+
+ g_free(src);
+ g_free(dest);
+
+ return result;
+}
+
static FolderItem *mh_create_folder(Folder *folder, FolderItem *parent,
const gchar *name)
{
if (!is_dir_exist(path))
if (make_dir_hier(path) != 0)
return NULL;
-
+
real_name = mh_filename_from_utf8(name);
fullpath = g_strconcat(path, G_DIR_SEPARATOR_S, real_name, NULL);
g_free(real_name);
g_free(path);
+ if (to_number(name) > 0) {
+ MsgInfo *info = folder_item_get_msginfo(parent, to_number(name));
+ if (info != NULL) {
+ gboolean ok = mh_renumber_msg(info);
+ procmsg_msginfo_free(&info);
+ if (!ok) {
+ g_free(fullpath);
+ return NULL;
+ }
+ }
+ }
+
if (make_dir(fullpath) < 0) {
g_free(fullpath);
return NULL;
static gint mh_remove_folder(Folder *folder, FolderItem *item)
{
gchar *path;
+ gint ret;
cm_return_val_if_fail(folder != NULL, -1);
cm_return_val_if_fail(item != NULL, -1);
cm_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);
+ if ((ret = remove_dir_recursive(path)) < 0) {
+ g_warning("can't remove directory '%s'", path);
g_free(path);
- return -1;
+ return ret;
}
g_free(path);
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 *real_path, *entry, *utf8entry, *utf8name;
+ gchar *entry, *utf8entry, *utf8name, *path;
gint n_msg = 0;
+ GError *error = NULL;
cm_return_if_fail(item != NULL);
cm_return_if_fail(item->folder != NULL);
folder = item->folder;
- real_path = item->path ? mh_filename_from_utf8(item->path) : g_strdup(".");
-#ifdef G_OS_WIN32
- dir = g_dir_open(real_path, 0, NULL);
+ path = folder_item_get_path(item);
+ debug_print("mh_scan_tree_recursive() opening '%s'\n", path);
+ dir = g_dir_open(path, 0, &error);
if (!dir) {
- g_warning("failed to open directory: %s\n", real_path);
- g_free(real_path);
- return;
- }
-#else
- dp = opendir(real_path);
- if (!dp) {
- FILE_OP_ERROR(real_path, "opendir");
+ g_warning("failed to open directory '%s': %s (%d)",
+ path, error->message, error->code);
+ g_error_free(error);
+ g_free(path);
return;
}
-#endif
- g_free(real_path);
debug_print("scanning %s ...\n",
item->path ? item->path
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;
+ entry = g_strconcat(path, G_DIR_SEPARATOR_S, dir_name, NULL);
+
utf8name = mh_filename_to_utf8(dir_name);
if (item->path)
utf8entry = g_strconcat(item->path, G_DIR_SEPARATOR_S,
utf8name, NULL);
else
utf8entry = g_strdup(utf8name);
- entry = mh_filename_from_utf8(utf8entry);
- if (
-#if !defined(G_OS_WIN32) && !defined(MAEMO) && 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(MAEMO) && defined(HAVE_DIRENT_D_TYPE)
- )
-#endif
- ) {
+ if (g_file_test(entry, G_FILE_TEST_IS_DIR)) {
FolderItem *new_item = NULL;
GNode *node;
node = item->node;
for (node = node->children; node != NULL; node = node->next) {
FolderItem *cur_item = FOLDER_ITEM(node->data);
- gchar *curpath = mh_filename_from_utf8(cur_item->path);
+ gchar *curpath = folder_item_get_path(cur_item);
if (!strcmp2(curpath, entry)) {
new_item = cur_item;
g_free(curpath);
g_free(utf8name);
}
-#ifdef G_OS_WIN32
g_dir_close(dir);
-#else
- closedir(dp);
-#endif
+ g_free(path);
mh_set_mtime(folder, item);
}
oldpathlen = strlen(oldpath);
if (strncmp(oldpath, item->path, oldpathlen) != 0) {
- g_warning("path doesn't match: %s, %s\n", oldpath, item->path);
+ g_warning("path doesn't match: %s, %s", oldpath, item->path);
return TRUE;
}
gchar *real_path = g_filename_from_utf8(path, -1, NULL, NULL, NULL);
if (!real_path) {
- g_warning("mh_filename_from_utf8: failed to convert character set\n");
+ g_warning("mh_filename_from_utf8: failed to convert character set");
real_path = g_strdup(path);
}
{
gchar *utf8path = g_filename_to_utf8(path, -1, NULL, NULL, NULL);
if (!utf8path) {
- g_warning("mh_filename_to_utf8: failed to convert character set\n");
+ g_warning("mh_filename_to_utf8: failed to convert character set");
utf8path = g_strdup(path);
}
if (fclose(mh_sequences_new_fp) == EOF)
err = TRUE;
- if (!err)
- g_rename(mh_sequences_new, mh_sequences_old);
+ if (!err) {
+ if (g_rename(mh_sequences_new, mh_sequences_old) < 0)
+ FILE_OP_ERROR(mh_sequences_new, "rename");
+ }
g_free(sequence);
procmsg_msg_list_free(msglist);
}
static void mh_set_mtime(Folder *folder, FolderItem *item)
{
- struct stat s;
+ GStatBuf s;
gchar *path = folder_item_get_path(item);
cm_return_if_fail(path != NULL);