X-Git-Url: http://git.claws-mail.org/?p=claws.git;a=blobdiff_plain;f=src%2Fmbox_folder.c;h=a0d4097686ee4cefcf41f5633bbadb98f4d8a08b;hp=ded6482cb06a480dabc15bc41d92db39846ae63a;hb=e30983987463bb4a1937f1a604bd4ce848967332;hpb=dcd3de58ec68f01806b64edaab9cd33e63cc028c diff --git a/src/mbox_folder.c b/src/mbox_folder.c index ded6482cb..a0d409768 100644 --- a/src/mbox_folder.c +++ b/src/mbox_folder.c @@ -1,3 +1,22 @@ +/* + * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client + * Copyright (C) 1999-2001 Hiroyuki Yamamoto & 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 + * 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. + */ + #include #include #include @@ -16,6 +35,10 @@ #define MSGBUFSIZE 8192 +static void mbox_folder_init (Folder *folder, + const gchar *name, + const gchar *path); + static gboolean mbox_write_data(FILE * mbox_fp, FILE * new_fp, gchar * new_filename, gint size); static gboolean mbox_rewrite(gchar * mbox); @@ -23,7 +46,51 @@ static gboolean mbox_purge_deleted(gchar * mbox); static gchar * mbox_get_new_path(FolderItem * parent, gchar * name); static gchar * mbox_get_folderitem_name(gchar * name); +MsgInfo *mbox_fetch_msginfo(Folder *folder, FolderItem *item, gint num); +GSList *mbox_get_num_list(Folder *folder, FolderItem *item); +gboolean mbox_check_msgnum_validity(Folder *folder, FolderItem *item); + +Folder *mbox_folder_new(const gchar *name, const gchar *path) +{ + Folder *folder; + + folder = (Folder *)g_new0(MBOXFolder, 1); + mbox_folder_init(folder, name, path); + + return folder; +} + +void mbox_folder_destroy(MBOXFolder *folder) +{ + folder_local_folder_destroy(LOCAL_FOLDER(folder)); +} + +static void mbox_folder_init(Folder *folder, const gchar *name, const gchar *path) +{ + folder->type = F_MBOX; + folder_local_folder_init(folder, name, path); + +/* + folder->get_msg_list = mbox_get_msg_list; +*/ + folder->fetch_msg = mbox_fetch_msg; + folder->fetch_msginfo = mbox_fetch_msginfo; + folder->add_msg = mbox_add_msg; + folder->copy_msg = mbox_copy_msg; + folder->remove_msg = mbox_remove_msg; + folder->remove_all_msg = mbox_remove_all_msg; +/* + folder->scan = mbox_scan_folder; +*/ + folder->get_num_list = mbox_get_num_list; + folder->create_tree = mbox_create_tree; + folder->create_folder = mbox_create_folder; + folder->rename_folder = mbox_rename_folder; + folder->remove_folder = mbox_remove_folder; + folder->check_msgnum_validity + = mbox_check_msgnum_validity; +} static gchar * mbox_folder_create_parent(const gchar * path) { @@ -98,7 +165,7 @@ static gboolean mbox_file_lock_file(gchar * base) FILE *lockfp; lockfile = g_strdup_printf("%s.%d", base, getpid()); - if ((lockfp = fopen(lockfile, "w")) == NULL) { + if ((lockfp = fopen(lockfile, "wb")) == NULL) { FILE_OP_ERROR(lockfile, "fopen"); g_warning(_("can't create lock file %s\n"), lockfile); g_warning(_("use 'flock' instead of 'file' if possible.\n")); @@ -301,6 +368,11 @@ struct _message gboolean fetched; }; +#define MSG_IS_INVALID(msg) \ + ((msg).perm_flags == (msg).tmp_flags && (msg).tmp_flags == -1) + +#define MSG_SET_INVALID(msg) \ + ((msg).perm_flags = (msg).tmp_flags = -1) static int startFrom(char * s) { @@ -381,8 +453,8 @@ static mailfile * mailfile_init_from_file(FILE * f, gchar * filename) data->content = 0; data->messageid = NULL; data->fromspace = NULL; - data->flags = -1; - data->old_flags = -1; + MSG_SET_INVALID(data->flags); + MSG_SET_INVALID(data->old_flags); data->fetched = FALSE; msg_list = g_list_append(msg_list, (gpointer) data); @@ -477,7 +549,7 @@ static mailfile * mailfile_init(char * filename) FILE * f; mailfile * mf; - f = fopen(filename, "r"); + f = fopen(filename, "rb"); if (f == NULL) { mailfile_error = MAILFILE_ERROR_FILE_NOT_FOUND; @@ -515,7 +587,7 @@ static char * readfile(char * filename, int offset, int max_offset) int bread; FILE * handle; - handle = fopen(filename, "r"); + handle = fopen(filename, "rb"); if (handle == NULL) { mailfile_error = MAILFILE_ERROR_FILE_NOT_FOUND; @@ -617,7 +689,7 @@ static int mailfile_find_deleted(mailfile f, char * filename) { FILE * handle; - handle = fopen(filename, "r"); + handle = fopen(filename, "rb"); while (elt) { struct _message m = elt->data; @@ -655,19 +727,21 @@ static MsgInfo *mbox_parse_msg(FILE * fp, struct _message * msg, FolderItem *item) { MsgInfo *msginfo; - MsgFlags flags = MSG_NEW|MSG_UNREAD; + MsgFlags flags = { 0, 0 }; + + MSG_SET_PERM_FLAGS(flags, MSG_NEW | MSG_UNREAD); g_return_val_if_fail(fp != NULL, NULL); if (item != 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_file_parse(fp, flags, FALSE); + msginfo = procheader_parse_stream(fp, flags, FALSE, FALSE); if (!msginfo) return NULL; @@ -733,7 +807,7 @@ static void mbox_cache_get_msginfo(gchar * filename, GList * msg_list) { FILE * fp; - fp = fopen(filename, "r"); + fp = fopen(filename, "rb"); if (fp == NULL) return; @@ -880,9 +954,7 @@ static void mbox_cache_synchronize_lists(GList * old_msg_list, if ((strcmp(msg->messageid, msg2->messageid) == 0) && (strcmp(msg->fromspace, msg2->fromspace) == 0)) { - if ((msg2->flags & MSG_PERMANENT_FLAG_MASK) != - (msg2->old_flags & - MSG_PERMANENT_FLAG_MASK)) { + if (msg2->flags.perm_flags != msg2->old_flags.perm_flags) { msg->flags = msg2->flags; break; } @@ -1121,7 +1193,7 @@ GSList *mbox_get_msg_list(Folder *folder, FolderItem *item, gboolean use_cache) mbox_purge_deleted(mbox_path); - fp = fopen(mbox_path, "r"); + fp = fopen(mbox_path, "rb"); if (fp == NULL) { g_free(mbox_path); @@ -1140,12 +1212,12 @@ GSList *mbox_get_msg_list(Folder *folder, FolderItem *item, gboolean use_cache) msg = (struct _message *) l->data; - if (msg->flags == -1 || !MSG_IS_REALLY_DELETED(msg->flags)) { + if (MSG_IS_INVALID(msg->flags) || !MSG_IS_REALLY_DELETED(msg->flags)) { fseek(fp, msg->header, SEEK_SET); msginfo = mbox_parse_msg(fp, msg, item); - if (msg->flags != -1) + if (!MSG_IS_INVALID(msg->flags)) msginfo->flags = msg->flags; else { msg->old_flags = msginfo->flags; @@ -1155,7 +1227,7 @@ GSList *mbox_get_msg_list(Folder *folder, FolderItem *item, gboolean use_cache) mlist = g_slist_append(mlist, msginfo); } else { - msg->flags = MSG_REALLY_DELETED; + MSG_SET_PERM_FLAGS(msg->flags, MSG_REALLY_DELETED); } } @@ -1195,7 +1267,7 @@ static gboolean mbox_extract_msg(FolderItem * item, gint msgnum, if (mbox_path == NULL) return FALSE; - src = fopen(mbox_path, "r"); + src = fopen(mbox_path, "rb"); if (src == NULL) { g_free(mbox_path); return FALSE; @@ -1230,7 +1302,7 @@ static gboolean mbox_extract_msg(FolderItem * item, gint msgnum, fseek(src, offset, SEEK_SET); - dest = fopen(dest_filename, "w"); + dest = fopen(dest_filename, "wb"); if (dest == NULL) { mbox_unlock_file(src, mbox_path); fclose(src); @@ -1289,7 +1361,6 @@ gchar *mbox_fetch_msg(Folder *folder, FolderItem *item, gint num) gchar *filename; g_return_val_if_fail(item != NULL, NULL); - g_return_val_if_fail(num > 0 && num <= item->last_num, NULL); path = folder_item_get_path(item); if (!is_dir_exist(path)) @@ -1324,7 +1395,7 @@ gint mbox_add_msg(Folder *folder, FolderItem *dest, const gchar *file, if (dest->last_num < 0) return -1; } - src_fp = fopen(file, "r"); + src_fp = fopen(file, "rb"); if (src_fp == NULL) { return -1; } @@ -1333,7 +1404,7 @@ gint mbox_add_msg(Folder *folder, FolderItem *dest, const gchar *file, if (mbox_path == NULL) return -1; - dest_fp = fopen(mbox_path, "a"); + dest_fp = fopen(mbox_path, "ab"); if (dest_fp == NULL) { fclose(src_fp); g_free(mbox_path); @@ -1363,7 +1434,7 @@ gint mbox_add_msg(Folder *folder, FolderItem *dest, const gchar *file, if (stat(file, &s) < 0) { mbox_unlock_file(dest_fp, mbox_path); - g_warning(_("unvalid file - %s.\n"), file); + g_warning(_("invalid file - %s.\n"), file); fclose(dest_fp); fclose(src_fp); g_free(mbox_path); @@ -1444,9 +1515,9 @@ gint mbox_remove_msg(Folder *folder, FolderItem *item, gint num) msg = mbox_cache_get_msg(mbox_path, num); g_free(mbox_path); - + if (msg != NULL) - MSG_SET_FLAGS(msg->flags, MSG_REALLY_DELETED); + MSG_SET_PERM_FLAGS(msg->flags, MSG_REALLY_DELETED); return 0; } @@ -1460,7 +1531,7 @@ gint mbox_remove_all_msg(Folder *folder, FolderItem *item) if (mbox_path == NULL) return -1; - fp = fopen(mbox_path, "w"); + fp = fopen(mbox_path, "wb"); if (fp == NULL) { g_free(mbox_path); return -1; @@ -1693,9 +1764,9 @@ void mbox_scan_folder(Folder *folder, FolderItem *item) struct _message * msg = (struct _message *) l->data; if (!MSG_IS_REALLY_DELETED(msg->flags)) total ++; - if (MSG_IS_NEW(msg->flags)) + if (MSG_IS_NEW(msg->flags) && !MSG_IS_IGNORE_THREAD(msg->flags)) new ++; - if (MSG_IS_UNREAD(msg->flags)) + if (MSG_IS_UNREAD(msg->flags) && !MSG_IS_IGNORE_THREAD(msg->flags)) unread ++; } @@ -1803,7 +1874,7 @@ static gboolean mbox_write_message(FILE * mbox_fp, FILE * new_fp, g_ptr_array_free(headers, FALSE); - if (msg->flags != -1) { + if (!MSG_IS_INVALID(msg->flags)) { /* Status header */ fwrite("Status: ", strlen("Status: "), 1, new_fp); if (!MSG_IS_UNREAD(msg->flags)) @@ -1812,9 +1883,11 @@ static gboolean mbox_write_message(FILE * mbox_fp, FILE * new_fp, fwrite("\n", 1, 1, new_fp); /* X-Status header */ - if (msg->flags & - (MSG_REALLY_DELETED | MSG_MARKED | MSG_DELETED - | MSG_REPLIED | MSG_FORWARDED)) { + if (MSG_IS_REALLY_DELETED(msg->flags) + || MSG_IS_MARKED(msg->flags) + || MSG_IS_DELETED(msg->flags) + || MSG_IS_REPLIED(msg->flags) + || MSG_IS_FORWARDED(msg->flags)) { fwrite("X-Status: ", strlen("X-Status: "), 1, new_fp); if (MSG_IS_REALLY_DELETED(msg->flags)) fwrite("D", 1, 1, new_fp); /* really deleted */ @@ -1901,13 +1974,13 @@ static gboolean mbox_rewrite(gchar * mbox) debug_print(_("save modification - %s\n"), mbox); - mbox_fp = fopen(mbox, "r+"); + mbox_fp = fopen(mbox, "rb+"); mbox_lockwrite_file(mbox_fp, mbox); mbox_cache_synchronize_from_file(mbox_fp, mbox, TRUE); new = g_strconcat(mbox, ".", itos((int) mbox), NULL); - new_fp = fopen(new, "w"); + new_fp = fopen(new, "wb"); if (change_file_mode_rw(new_fp, new) < 0) { FILE_OP_ERROR(new, "chmod"); @@ -1982,7 +2055,7 @@ static gboolean mbox_purge_deleted(gchar * mbox) for(l = msg_list ; l != NULL ; l = g_list_next(l)) { struct _message * msg = (struct _message *) l->data; - if (msg->flags != -1 && MSG_IS_REALLY_DELETED(msg->flags)) { + if (!MSG_IS_INVALID(msg->flags) && MSG_IS_REALLY_DELETED(msg->flags)) { modification = TRUE; break; } @@ -1995,13 +2068,13 @@ static gboolean mbox_purge_deleted(gchar * mbox) debug_print(_("purge deleted messages - %s\n"), mbox); - mbox_fp = fopen(mbox, "r+"); + mbox_fp = fopen(mbox, "rb+"); mbox_lockwrite_file(mbox_fp, mbox); mbox_cache_synchronize_from_file(mbox_fp, mbox, TRUE); new = g_strconcat(mbox, ".", itos((int) mbox), NULL); - new_fp = fopen(new, "w"); + new_fp = fopen(new, "wb"); if (change_file_mode_rw(new_fp, new) < 0) { FILE_OP_ERROR(new, "chmod"); @@ -2016,7 +2089,7 @@ static gboolean mbox_purge_deleted(gchar * mbox) msg_list = mbox_cache_get_msg_list(mbox); for(l = msg_list ; l != NULL ; l = g_list_next(l)) { struct _message * msg = (struct _message *) l->data; - if (msg->flags == -1 || !MSG_IS_REALLY_DELETED(msg->flags)) { + if (MSG_IS_INVALID(msg->flags) || !MSG_IS_REALLY_DELETED(msg->flags)) { if (!mbox_write_message(mbox_fp, new_fp, new, msg)) { result = FALSE; break; @@ -2129,7 +2202,7 @@ FolderItem *mbox_create_folder(Folder *folder, FolderItem *parent, foldername = mbox_get_folderitem_name((gchar *) name); - new_item = folder_item_new(foldername, path); + new_item = folder_item_new(folder, foldername, path); folder_item_append(parent, new_item); if (!strcmp(name, "inbox")) { @@ -2195,3 +2268,119 @@ gint mbox_remove_folder(Folder *folder, FolderItem *item) return 0; } +GSList *mbox_get_num_list(Folder *folder, FolderItem *item) +{ + GSList *mlist; + GList * l; + FILE * fp; + gchar * mbox_path; + + mlist = NULL; + + mbox_path = mbox_folder_get_path(item); + + if (mbox_path == NULL) + return NULL; + + mbox_purge_deleted(mbox_path); + + fp = fopen(mbox_path, "rb"); + + if (fp == NULL) { + g_free(mbox_path); + return NULL; + } + + mbox_lockread_file(fp, mbox_path); + + mbox_cache_synchronize_from_file(fp, mbox_path, TRUE); + + item->last_num = mbox_cache_get_count(mbox_path); + + for(l = mbox_cache_get_msg_list(mbox_path) ; l != NULL ; + l = g_list_next(l)) { + struct _message * msg; + + msg = (struct _message *) l->data; + + if (MSG_IS_INVALID(msg->flags) || !MSG_IS_REALLY_DELETED(msg->flags)) { + mlist = g_slist_append(mlist, GINT_TO_POINTER(msg->msgnum)); + } else { + MSG_SET_PERM_FLAGS(msg->flags, MSG_REALLY_DELETED); + } + } + + mbox_unlock_file(fp, mbox_path); + + g_free(mbox_path); + + fclose(fp); + + return mlist; +} + +MsgInfo *mbox_fetch_msginfo(Folder *folder, FolderItem *item, gint num) +{ + gchar *mbox_path; + struct _message *msg; + FILE *src; + MsgInfo *msginfo; + + g_return_val_if_fail(folder != NULL, NULL); + g_return_val_if_fail(item != NULL, NULL); + + mbox_path = mbox_folder_get_path(item); + + g_return_val_if_fail(mbox_path != NULL, NULL); + + src = fopen(mbox_path, "rb"); + if (src == NULL) { + g_free(mbox_path); + return NULL; + } + mbox_lockread_file(src, mbox_path); + mbox_cache_synchronize_from_file(src, mbox_path, TRUE); + + msg = mbox_cache_get_msg(mbox_path, num); + if (msg == NULL) { + mbox_unlock_file(src, mbox_path); + fclose(src); + g_free(mbox_path); + return NULL; + } + + fseek(src, msg->header, SEEK_SET); + msginfo = mbox_parse_msg(src, msg, item); + + mbox_unlock_file(src, mbox_path); + fclose(src); + g_free(mbox_path); + + return msginfo; +} + +gboolean mbox_check_msgnum_validity(Folder *folder, FolderItem *item) +{ + mboxcache * old_cache; + gboolean scan_new = TRUE; + struct stat s; + gchar *filename; + + filename = mbox_folder_get_path(item); + + old_cache = mbox_cache_get_mbox(filename); + + if (old_cache != NULL) { + if (stat(filename, &s) < 0) { + FILE_OP_ERROR(filename, "stat"); + } else if (old_cache->mtime == s.st_mtime) { + debug_print("Folder is not modified.\n"); + scan_new = FALSE; + } + } + + g_free(filename); + + return !scan_new; +} +