From 4af086d64103b05104bf6d13847f8e656069f234 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ho=C3=A0=20Vi=C3=AAt=20Dinh?= Date: Sun, 27 May 2001 22:40:29 +0000 Subject: [PATCH] mbox format completed --- ChangeLog.claws | 53 ++ src/compose.c | 12 + src/filtering.c | 53 +- src/folder.c | 183 +++++- src/folder.h | 1 + src/foldersel.c | 3 +- src/folderview.c | 102 +++- src/folderview.h | 2 + src/mainwindow.c | 65 ++- src/mbox.c | 2 + src/mbox_folder.c | 1237 ++++++++++++++++++++++++++++++++--------- src/mbox_folder.h | 10 + src/mh.c | 75 +++ src/prefs_filtering.c | 7 +- src/procheader.c | 20 +- src/procmsg.c | 1 + src/procmsg.h | 7 +- src/summaryview.c | 39 +- src/textview.c | 6 +- 19 files changed, 1560 insertions(+), 318 deletions(-) diff --git a/ChangeLog.claws b/ChangeLog.claws index 3734ba6da..4031d7892 100644 --- a/ChangeLog.claws +++ b/ChangeLog.claws @@ -1,3 +1,56 @@ +2001-05-28 [hoa] + + * src/compose.c + handling flags for mbox format + + * src/filtering.c + use of mark file only for MH format + handling flags for mbox format + filtering cannot yet move or copy mails to mbox folders. + + * src/folder.[ch] + changed move_msg, copy_msg, + move_msgs_with_dest, copy_msgs_with_dest functions + uses only folder->copy_msg() function + uses folder->finished_copy() to handle the destination + folder at the end of the copy or move operation. + + * src/foldersel.c + included mbox directories. + + * src/folderview.[ch] + * src/mainwindow.c + handle folders operation for mbox format + + * src/mbox.c + disable conversion of "From " header + + * src/mbox_folder.[ch] + completion of mbox format handling + + * src/mh.c + changed mh_copy_msg() function and + removed mh_move_msg(), mh_move_msgs_with_dest(), + mh_copy_msgs_with_dest() + + * src/prefs_filtering.c + removed some warnings + + * src/procheader.c + handling flags for mbox format + handling of "From " header + + * src/procmsg.[ch] + removed data field + added MSG_REALLY_DELETED flags to handle deletion of + messages in mbox format. + + * src/summaryview.c + handling flags for mbox format + + * src/textview.c + "From " headers display fixed. + 2001-05-27 [alfons] * src/textview.c: diff --git a/src/compose.c b/src/compose.c index 0b5d400d2..6153a551e 100644 --- a/src/compose.c +++ b/src/compose.c @@ -464,6 +464,14 @@ Compose * compose_new_with_recipient(PrefsAccount *account, const gchar *to) return compose; } +#define CHANGE_FLAGS(msginfo) \ +{ \ +if (msginfo->folder->folder->change_flags != NULL) \ +msginfo->folder->folder->change_flags(msginfo->folder->folder, \ + msginfo->folder, \ + msginfo); \ +} + void compose_reply(MsgInfo *msginfo, gboolean quote, gboolean to_all, gboolean to_author) { @@ -492,6 +500,8 @@ void compose_reply(MsgInfo *msginfo, gboolean quote, gboolean to_all, MSG_UNSET_FLAGS(msginfo->flags, MSG_FORWARDED); MSG_SET_FLAGS(msginfo->flags, MSG_REPLIED); + CHANGE_FLAGS(msginfo); + compose = compose_create(reply_account); compose->mode = COMPOSE_REPLY; @@ -554,6 +564,8 @@ Compose * compose_forward(PrefsAccount * account, MsgInfo *msginfo, MSG_UNSET_FLAGS(msginfo->flags, MSG_REPLIED); MSG_SET_FLAGS(msginfo->flags, MSG_FORWARDED); + CHANGE_FLAGS(msginfo); + compose = compose_create(account); compose->mode = COMPOSE_FORWARD; diff --git a/src/filtering.c b/src/filtering.c index e5e45a845..48d0188ef 100644 --- a/src/filtering.c +++ b/src/filtering.c @@ -175,24 +175,27 @@ static gboolean filteringaction_update_mark(MsgInfo * info) gchar * dest_path; FILE * fp; - dest_path = folder_item_get_path(info->folder); - if (!is_dir_exist(dest_path)) - make_dir_hier(dest_path); - - if (dest_path == NULL) { - g_warning(_("Can't open mark file.\n")); - return FALSE; - } - - if ((fp = procmsg_open_mark_file(dest_path, TRUE)) - == NULL) { - g_warning(_("Can't open mark file.\n")); - return FALSE; + if (info->folder->folder->type == F_MH) { + dest_path = folder_item_get_path(info->folder); + if (!is_dir_exist(dest_path)) + make_dir_hier(dest_path); + + if (dest_path == NULL) { + g_warning(_("Can't open mark file.\n")); + return FALSE; + } + + if ((fp = procmsg_open_mark_file(dest_path, TRUE)) + == NULL) { + g_warning(_("Can't open mark file.\n")); + return FALSE; + } + + procmsg_write_flags(info, fp); + fclose(fp); + return TRUE; } - - procmsg_write_flags(info, fp); - fclose(fp); - return TRUE; + return FALSE; } /* @@ -201,6 +204,14 @@ static gboolean filteringaction_update_mark(MsgInfo * info) return value : return TRUE if the action could be applied */ +#define CHANGE_FLAGS(msginfo) \ +{ \ +if (msginfo->folder->folder->change_flags != NULL) \ +msginfo->folder->folder->change_flags(msginfo->folder->folder, \ + msginfo->folder, \ + msginfo); \ +} + static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info, GHashTable *folder_table) { @@ -269,24 +280,32 @@ static gboolean filteringaction_apply(FilteringAction * action, MsgInfo * info, MSG_SET_FLAGS(info->flags, MSG_MARKED); filteringaction_update_mark(info); + CHANGE_FLAGS(info); + return TRUE; case MATCHING_ACTION_UNMARK: MSG_UNSET_FLAGS(info->flags, MSG_MARKED); filteringaction_update_mark(info); + CHANGE_FLAGS(info); + return TRUE; case MATCHING_ACTION_MARK_AS_READ: MSG_UNSET_FLAGS(info->flags, MSG_UNREAD | MSG_NEW); filteringaction_update_mark(info); + CHANGE_FLAGS(info); + return TRUE; case MATCHING_ACTION_MARK_AS_UNREAD: MSG_SET_FLAGS(info->flags, MSG_UNREAD | MSG_NEW); filteringaction_update_mark(info); + CHANGE_FLAGS(info); + return TRUE; case MATCHING_ACTION_FORWARD: diff --git a/src/folder.c b/src/folder.c index 3f363840a..e1a040059 100644 --- a/src/folder.c +++ b/src/folder.c @@ -548,6 +548,7 @@ gint folder_item_add_msg(FolderItem *dest, const gchar *file, return num; } +/* gint folder_item_move_msg(FolderItem *dest, MsgInfo *msginfo) { Folder *folder; @@ -568,7 +569,47 @@ gint folder_item_move_msg(FolderItem *dest, MsgInfo *msginfo) return num; } +*/ + +gint folder_item_move_msg(FolderItem *dest, MsgInfo *msginfo) +{ + Folder *folder; + gint num; + gchar * filename; + Folder * src_folder; + + g_return_val_if_fail(dest != NULL, -1); + g_return_val_if_fail(msginfo != NULL, -1); + + folder = dest->folder; + + g_return_val_if_fail(folder->scan != NULL, -1); + g_return_val_if_fail(folder->remove_msg != NULL, -1); + g_return_val_if_fail(folder->copy_msg != NULL, -1); + if (dest->last_num < 0) folder->scan(folder, dest); + + src_folder = msginfo->folder->folder; + + num = folder->copy_msg(folder, dest, msginfo); + if (num != -1) + src_folder->remove_msg(src_folder, + msginfo->folder, + msginfo->msgnum); + + if (folder->finished_copy) + folder->finished_copy(folder, dest); + + src_folder = msginfo->folder->folder; + + if (msginfo->folder && src_folder->scan) + src_folder->scan(src_folder, msginfo->folder); + folder->scan(folder, dest); + + return num; +} + +/* gint folder_item_move_msgs_with_dest(FolderItem *dest, GSList *msglist) { Folder *folder; @@ -589,7 +630,54 @@ gint folder_item_move_msgs_with_dest(FolderItem *dest, GSList *msglist) return num; } +*/ + +gint folder_item_move_msgs_with_dest(FolderItem *dest, GSList *msglist) +{ + Folder *folder; + FolderItem * item; + GSList * l; + gchar * filename; + + g_return_val_if_fail(dest != NULL, -1); + g_return_val_if_fail(msglist != NULL, -1); + + folder = dest->folder; + + g_return_val_if_fail(folder->scan != NULL, -1); + g_return_val_if_fail(folder->copy_msg != NULL, -1); + g_return_val_if_fail(folder->remove_msg != NULL, -1); + + if (dest->last_num < 0) folder->scan(folder, dest); + + item = NULL; + for(l = msglist ; l != NULL ; l = g_slist_next(l)) { + MsgInfo * msginfo = (MsgInfo *) l->data; + + if (!item && msginfo->folder != NULL) + item = msginfo->folder; + + if (folder->copy_msg(folder, dest, msginfo) != -1) + item->folder->remove_msg(item->folder, + msginfo->folder, + msginfo->msgnum); + } + + if (folder->finished_copy) + folder->finished_copy(folder, dest); + + printf("là scan\n"); + + if (item && item->folder->scan) + item->folder->scan(item->folder, item); + folder->scan(folder, dest); + + printf("ici scan\n"); + + return dest->last_num; +} +/* gint folder_item_copy_msg(FolderItem *dest, MsgInfo *msginfo) { Folder *folder; @@ -610,7 +698,36 @@ gint folder_item_copy_msg(FolderItem *dest, MsgInfo *msginfo) return num; } +*/ +gint folder_item_copy_msg(FolderItem *dest, MsgInfo *msginfo) +{ + Folder *folder; + gint num; + gchar * filename; + Folder * src_folder; + + g_return_val_if_fail(dest != NULL, -1); + g_return_val_if_fail(msginfo != NULL, -1); + + folder = dest->folder; + + g_return_val_if_fail(folder->scan != NULL, -1); + g_return_val_if_fail(folder->copy_msg != NULL, -1); + + if (dest->last_num < 0) folder->scan(folder, dest); + + num = folder->copy_msg(folder, dest, msginfo); + + if (folder->finished_copy) + folder->finished_copy(folder, dest); + + folder->scan(folder, dest); + + return num; +} + +/* gint folder_item_copy_msgs_with_dest(FolderItem *dest, GSList *msglist) { Folder *folder; @@ -631,6 +748,38 @@ gint folder_item_copy_msgs_with_dest(FolderItem *dest, GSList *msglist) return num; } +*/ + +gint folder_item_copy_msgs_with_dest(FolderItem *dest, GSList *msglist) +{ + Folder *folder; + gint num; + GSList * l; + gchar * filename; + + g_return_val_if_fail(dest != NULL, -1); + g_return_val_if_fail(msglist != NULL, -1); + + folder = dest->folder; + + g_return_val_if_fail(folder->scan != NULL, -1); + g_return_val_if_fail(folder->copy_msg != NULL, -1); + + if (dest->last_num < 0) folder->scan(folder, dest); + + for(l = msglist ; l != NULL ; l = g_slist_next(l)) { + MsgInfo * msginfo = (MsgInfo *) l->data; + + folder->copy_msg(folder, dest, msginfo); + } + + if (folder->finished_copy) + folder->finished_copy(folder, dest); + + folder->scan(folder, dest); + + return dest->last_num; +} gint folder_item_remove_msg(FolderItem *item, gint num) { @@ -653,10 +802,12 @@ gint folder_item_remove_all_msg(FolderItem *item) Folder *folder; g_return_val_if_fail(item != NULL, -1); + + folder = item->folder; + g_return_val_if_fail(folder->scan != NULL, -1); g_return_val_if_fail(folder->remove_all_msg != NULL, -1); - folder = item->folder; if (item->last_num < 0) folder->scan(folder, item); return folder->remove_all_msg(folder, item); @@ -738,10 +889,13 @@ static void folder_init(Folder *folder, FolderType type, const gchar *name) folder->get_msg_list = mh_get_msg_list; folder->fetch_msg = mh_fetch_msg; folder->add_msg = mh_add_msg; + /* folder->move_msg = mh_move_msg; folder->move_msgs_with_dest = mh_move_msgs_with_dest; folder->copy_msg = mh_copy_msg; folder->copy_msgs_with_dest = mh_copy_msgs_with_dest; + */ + folder->copy_msg = mh_copy_msg; folder->remove_msg = mh_remove_msg; folder->remove_all_msg = mh_remove_all_msg; folder->is_msg_changed = mh_is_msg_changed; @@ -755,8 +909,10 @@ static void folder_init(Folder *folder, FolderType type, const gchar *name) case F_IMAP: folder->get_msg_list = imap_get_msg_list; folder->fetch_msg = imap_fetch_msg; + /* folder->move_msg = imap_move_msg; folder->move_msgs_with_dest = imap_move_msgs_with_dest; + */ folder->remove_msg = imap_remove_msg; folder->remove_all_msg = imap_remove_all_msg; folder->scan = imap_scan_folder; @@ -775,18 +931,23 @@ static void folder_init(Folder *folder, FolderType type, const gchar *name) folder->add_msg = mbox_add_msg; folder->remove_all_msg = mbox_remove_all_msg; folder->remove_msg = mbox_remove_msg; - folder->update_mark = mbox_update_mark; + /* folder->move_msg = mbox_move_msg; folder->move_msgs_with_dest = mbox_move_msgs_with_dest; + folder->copy_msg = mbox_copy_msg; + folder->copy_msgs_with_dest = mbox_copy_msgs_with_dest; + */ + folder->copy_msg = mbox_copy_msg; + + 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->update_mark = mbox_update_mark; + folder->change_flags = mbox_change_flags; + folder->finished_copy = mbox_finished_copy; - /* - folder->remove_msg = mh_remove_msg; - folder->is_msg_changed = mh_is_msg_changed; - folder->scan_tree = mh_scan_tree; - folder->create_tree = mh_create_tree; - folder->create_folder = mh_create_folder; - folder->rename_folder = mh_rename_folder; - folder->remove_folder = mh_remove_folder;*/ break; default: } @@ -1021,7 +1182,7 @@ static void folder_write_list_recursive(GNode *node, gpointer data) xml_file_put_escape_str(fp, folder->name); fputs("\"", fp); } - if (folder->type == F_MH) { + if ((folder->type == F_MH) || (folder->type == F_MBOX)) { fputs(" path=\"", fp); xml_file_put_escape_str (fp, LOCAL_FOLDER(folder)->rootpath); diff --git a/src/folder.h b/src/folder.h index 9227f7fdc..64ea96df9 100644 --- a/src/folder.h +++ b/src/folder.h @@ -148,6 +148,7 @@ struct _Folder void (*change_flags) (Folder *folder, FolderItem *item, MsgInfo *info); + void (*finished_copy) (Folder * folder, FolderItem * item); }; struct _LocalFolder diff --git a/src/foldersel.c b/src/foldersel.c index e3e79d41d..61718698a 100644 --- a/src/foldersel.c +++ b/src/foldersel.c @@ -232,7 +232,8 @@ static void foldersel_set_tree(void) folder = FOLDER(list->data); g_return_if_fail(folder != NULL); - if (folder->type != F_MH) continue; + if ((folder->type != F_MH) && (folder->type != F_MBOX)) + continue; node = gtk_ctree_insert_gnode(GTK_CTREE(ctree), NULL, NULL, folder->node, diff --git a/src/folderview.c b/src/folderview.c index b4ea54fd2..8ead09c90 100644 --- a/src/folderview.c +++ b/src/folderview.c @@ -150,6 +150,9 @@ static void folderview_col_resized (GtkCList *clist, static void folderview_new_folder_cb (FolderView *folderview, guint action, GtkWidget *widget); +static void folderview_new_mbox_folder_cb(FolderView *folderview, + guint action, + GtkWidget *widget); static void folderview_rename_folder_cb (FolderView *folderview, guint action, GtkWidget *widget); @@ -199,6 +202,17 @@ static void folderview_drag_received_cb (GtkWidget *widget, guint time, FolderView *folderview); +static GtkItemFactoryEntry folderview_mbox_popup_entries[] = +{ + {N_("/Create _new folder..."), NULL, folderview_new_mbox_folder_cb, 0, NULL}, + {N_("/_Rename folder..."), NULL, folderview_rename_folder_cb, 0, NULL}, + {N_("/_Delete folder"), NULL, folderview_delete_folder_cb, 0, NULL}, + {N_("/---"), NULL, NULL, 0, ""}, + {N_("/Remove _mailbox"), NULL, folderview_remove_mailbox_cb, 0, NULL}, + {N_("/---"), NULL, NULL, 0, ""}, + {N_("/_Property..."), NULL, NULL, 0, NULL} +}; + static GtkItemFactoryEntry folderview_mail_popup_entries[] = { {N_("/Create _new folder..."), NULL, folderview_new_folder_cb, 0, NULL}, @@ -243,9 +257,11 @@ FolderView *folderview_create(void) GtkWidget *mail_popup; GtkWidget *news_popup; GtkWidget *imap_popup; + GtkWidget *mbox_popup; GtkItemFactory *mail_factory; GtkItemFactory *news_factory; GtkItemFactory *imap_factory; + GtkItemFactory *mbox_factory; gint n_entries; gint i; @@ -306,6 +322,12 @@ FolderView *folderview_create(void) n_entries, "", &news_factory, folderview); + n_entries = sizeof(folderview_mbox_popup_entries) / + sizeof(folderview_mbox_popup_entries[0]); + mbox_popup = menu_create_items(folderview_mbox_popup_entries, + n_entries, + "", &mbox_factory, + folderview); gtk_signal_connect(GTK_OBJECT(ctree), "key_press_event", GTK_SIGNAL_FUNC(folderview_key_pressed), @@ -340,6 +362,9 @@ FolderView *folderview_create(void) gtk_signal_connect(GTK_OBJECT(news_popup), "selection_done", GTK_SIGNAL_FUNC(folderview_popup_close), folderview); + gtk_signal_connect(GTK_OBJECT(mbox_popup), "selection_done", + GTK_SIGNAL_FUNC(folderview_popup_close), + folderview); /* drop callback */ gtk_drag_dest_set(ctree, GTK_DEST_DEFAULT_ALL & @@ -364,6 +389,8 @@ FolderView *folderview_create(void) folderview->imap_factory = imap_factory; folderview->news_popup = news_popup; folderview->news_factory = news_factory; + folderview->mbox_popup = mbox_popup; + folderview->mbox_factory = mbox_factory; gtk_widget_show_all(scrolledwin); @@ -969,8 +996,10 @@ void folderview_new_folder(FolderView *folderview) g_return_if_fail(item->folder != NULL); switch (item->folder->type) { - case F_MH: case F_MBOX: + folderview_new_mbox_folder_cb(folderview, 0, NULL); + break; + case F_MH: case F_MAILDIR: folderview_new_folder_cb(folderview, 0, NULL); break; @@ -1090,6 +1119,7 @@ static void folderview_button_pressed(GtkWidget *ctree, GdkEventButton *event, menu_set_insensitive_all(GTK_MENU_SHELL(folderview->mail_popup)); menu_set_insensitive_all(GTK_MENU_SHELL(folderview->imap_popup)); menu_set_insensitive_all(GTK_MENU_SHELL(folderview->news_popup)); + menu_set_insensitive_all(GTK_MENU_SHELL(folderview->mbox_popup)); if (folder->type == F_MH && item->parent == NULL) { menu_set_sensitive(folderview->mail_factory, @@ -1127,6 +1157,22 @@ static void folderview_button_pressed(GtkWidget *ctree, GdkEventButton *event, menu_set_sensitive(folderview->news_factory, "/Remove newsgroup", TRUE); } + if (folder->type == F_MBOX && item->parent == NULL) { + menu_set_sensitive(folderview->mbox_factory, + "/Create new folder...", TRUE); + menu_set_sensitive(folderview->mbox_factory, + "/Remove mailbox", TRUE); + } else if (folder->type == F_MBOX && item->stype != F_NORMAL) { + menu_set_sensitive(folderview->mbox_factory, + "/Create new folder...", TRUE); + } else if (folder->type == F_MBOX) { + menu_set_sensitive(folderview->mbox_factory, + "/Create new folder...", TRUE); + menu_set_sensitive(folderview->mbox_factory, + "/Rename folder...", TRUE); + menu_set_sensitive(folderview->mbox_factory, + "/Delete folder", TRUE); + } if (folder->type == F_MH) gtk_menu_popup(GTK_MENU(folderview->mail_popup), NULL, NULL, @@ -1137,6 +1183,9 @@ static void folderview_button_pressed(GtkWidget *ctree, GdkEventButton *event, else if (folder->type == F_NEWS) gtk_menu_popup(GTK_MENU(folderview->news_popup), NULL, NULL, NULL, NULL, event->button, event->time); + else if (folder->type == F_MBOX) + gtk_menu_popup(GTK_MENU(folderview->mbox_popup), NULL, NULL, + NULL, NULL, event->button, event->time); } static void folderview_button_released(GtkWidget *ctree, GdkEventButton *event, @@ -1187,6 +1236,7 @@ static void folderview_selected(GtkCTree *ctree, GtkCTreeNode *row, { static gboolean can_select = TRUE; /* exclusive lock */ FolderItem *item; + gchar * s = NULL; folderview->selected = row; @@ -1347,6 +1397,56 @@ static void folderview_new_folder_cb(FolderView *folderview, guint action, folder_write_list(); } +static void folderview_new_mbox_folder_cb(FolderView *folderview, guint action, + GtkWidget *widget) +{ + GtkCTree *ctree = GTK_CTREE(folderview->ctree); + gchar *text[N_FOLDER_COLS] = {NULL, "0", "0", "0"}; + FolderItem *item; + FolderItem *new_item; + gchar *new_folder; + GtkCTreeNode *node; + + if (!folderview->selected) return; + + item = gtk_ctree_node_get_row_data(ctree, folderview->selected); + g_return_if_fail(item != NULL); + g_return_if_fail(item->folder != NULL); + + new_folder = input_dialog(_("New folder"), + _("Input the name of new folder:"), + _("NewFolder")); + if (!new_folder) return; + + /* find whether the directory already exists */ + if (folderview_find_by_name(ctree, folderview->selected, new_folder)) { + alertpanel_error(_("The folder `%s' already exists."), + new_folder); + g_free(new_folder); + return; + } + + new_item = item->folder->create_folder(item->folder, item, new_folder); + g_free(new_folder); + if (!new_item) return; + + gtk_clist_freeze(GTK_CLIST(ctree)); + + text[COL_FOLDER] = new_item->name; + node = gtk_ctree_insert_node(ctree, folderview->selected, NULL, text, + FOLDER_SPACING, + folderxpm, folderxpmmask, + folderopenxpm, folderopenxpmmask, + FALSE, FALSE); + gtk_ctree_expand(ctree, folderview->selected); + gtk_ctree_node_set_row_data(ctree, node, new_item); + folderview_sort_folders(folderview, folderview->selected, item->folder); + + gtk_clist_thaw(GTK_CLIST(ctree)); + + folder_write_list(); +} + static void folderview_rename_folder_cb(FolderView *folderview, guint action, GtkWidget *widget) { diff --git a/src/folderview.h b/src/folderview.h index 1dd02fe06..9b8140a9d 100644 --- a/src/folderview.h +++ b/src/folderview.h @@ -38,10 +38,12 @@ struct _FolderView GtkWidget *mail_popup; GtkWidget *imap_popup; GtkWidget *news_popup; + GtkWidget *mbox_popup; GtkItemFactory *mail_factory; GtkItemFactory *imap_factory; GtkItemFactory *news_factory; + GtkItemFactory *mbox_factory; GtkCTreeNode *selected; GtkCTreeNode *opened; diff --git a/src/mainwindow.c b/src/mainwindow.c index c72750653..b84a5e493 100644 --- a/src/mainwindow.c +++ b/src/mainwindow.c @@ -147,6 +147,9 @@ static gint main_window_close_cb (GtkWidget *widget, static void add_mailbox_cb (MainWindow *mainwin, guint action, GtkWidget *widget); +static void add_mbox_cb (MainWindow *mainwin, + guint action, + GtkWidget *widget); static void update_folderview_cb (MainWindow *mainwin, guint action, GtkWidget *widget); @@ -191,8 +194,7 @@ static void toggle_toolbar_cb (MainWindow *mainwin, static void toggle_statusbar_cb (MainWindow *mainwin, guint action, GtkWidget *widget); - -static void separate_widget_cb(GtkCheckMenuItem *checkitem, guint action); +static void separate_widget_cb(GtkCheckMenuItem *checkitem, guint action); static void addressbook_open_cb (MainWindow *mainwin, guint action, @@ -351,6 +353,7 @@ static GtkItemFactoryEntry mainwin_entries[] = { {N_("/_File"), NULL, NULL, 0, ""}, {N_("/_File/_Add mailbox..."), NULL, add_mailbox_cb, 0, NULL}, + {N_("/_File/_Add mbox mailbox..."), NULL, add_mbox_cb, 0, NULL}, {N_("/_File/_Update folder tree"), NULL, update_folderview_cb, 0, NULL}, {N_("/_File/_Folder"), NULL, NULL, 0, ""}, {N_("/_File/_Folder/Create _new folder..."), @@ -1048,6 +1051,56 @@ void main_window_add_mailbox(MainWindow *mainwin) folderview_set(mainwin->folderview); } +void main_window_add_mbox(MainWindow *mainwin) +{ + gchar *path; + Folder *folder; + FolderItem * item; + + path = input_dialog(_("Add mbox mailbox"), + _("Input the location of mailbox."), + "mail"); + + if (!path) return; + + /* + if (folder_find_from_path(path)) { + alertpanel_error(_("The mailbox `%s' already exists."), path); + g_free(path); + return; + } + */ + + /* + if (!strcmp(path, "Mail")) + folder = folder_new(F_MBOX, _("Mailbox"), path); + else + */ + + folder = folder_new(F_MBOX, g_basename(path), path); + g_free(path); + + if (folder->create_tree(folder) < 0) { + alertpanel_error(_("Creation of the mailbox failed.")); + folder_destroy(folder); + return; + } + + folder_add(folder); + + item = folder_item_new(folder->name, NULL); + item->folder = folder; + folder->node = g_node_new(item); + + mbox_create_folder(folder, item, "inbox"); + mbox_create_folder(folder, item, "outbox"); + mbox_create_folder(folder, item, "queue"); + mbox_create_folder(folder, item, "draft"); + mbox_create_folder(folder, item, "trash"); + + folderview_set(mainwin->folderview); +} + void main_window_set_toolbar_sensitive(MainWindow *mainwin, gboolean sensitive) { gtk_widget_set_sensitive(mainwin->reply_btn, sensitive); @@ -1670,6 +1723,12 @@ static void add_mailbox_cb(MainWindow *mainwin, guint action, main_window_add_mailbox(mainwin); } +static void add_mbox_cb(MainWindow *mainwin, guint action, + GtkWidget *widget) +{ + main_window_add_mbox(mainwin); +} + static void update_folderview_cb(MainWindow *mainwin, guint action, GtkWidget *widget) { @@ -1820,7 +1879,7 @@ static void toggle_statusbar_cb(MainWindow *mainwin, guint action, } } -static void separate_widget_cb(GtkCheckMenuItem *checkitem, guint action) +static void separate_widget_cb(GtkCheckMenuItem *checkitem, guint action) { MainWindow *mainwin; SeparateType type; diff --git a/src/mbox.c b/src/mbox.c index ae55c9759..cf60a2c9a 100644 --- a/src/mbox.c +++ b/src/mbox.c @@ -116,6 +116,7 @@ gint proc_mbox(FolderItem *dest, const gchar *mbox, GHashTable *folder_table) FILE_OP_ERROR(tmp_file, "chmod"); /* convert unix From into Return-Path */ + /* startp = from_line + 5; endp = strchr(startp, ' '); if (endp == NULL) @@ -126,6 +127,7 @@ gint proc_mbox(FolderItem *dest, const gchar *mbox, GHashTable *folder_table) g_snprintf(from_line, sizeof(from_line), "Return-Path: %s\n", rpath); g_free(rpath); + */ FPUTS_TO_TMP_ABORT_IF_FAIL(from_line); FPUTS_TO_TMP_ABORT_IF_FAIL(buf); diff --git a/src/mbox_folder.c b/src/mbox_folder.c index d3243b942..bce84b9e9 100644 --- a/src/mbox_folder.c +++ b/src/mbox_folder.c @@ -14,8 +14,72 @@ #include "utils.h" #include "intl.h" +#define MSGBUFSIZE 8192 + static gboolean mbox_write_data(FILE * mbox_fp, FILE * new_fp, gchar * new_filename, gint size); +static gboolean mbox_rewrite(gchar * mbox); +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); + + + +static gchar *mbox_folder_get_path(FolderItem *item) +{ + gchar *folder_path; + gchar *path; + + g_return_val_if_fail(item != NULL, NULL); + + if (item->path && item->path[0] == G_DIR_SEPARATOR) { + return g_strdup(item->path); + } + + folder_path = g_strdup(LOCAL_FOLDER(item->folder)->rootpath); + g_return_val_if_fail(folder_path != NULL, NULL); + + if (folder_path[0] == G_DIR_SEPARATOR) { + if (item->path) { + path = g_strconcat(folder_path, G_DIR_SEPARATOR_S, + item->path, NULL); + } + else + path = g_strdup(folder_path); + } else { + if (item->path) + path = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, + folder_path, G_DIR_SEPARATOR_S, + item->path, NULL); + else + path = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, + folder_path, NULL); + } + + g_free(folder_path); + + + if (!is_file_exist(path) && item->parent != NULL) { + + gchar * parent_path; + gchar * new_path; + + parent_path = mbox_folder_get_path(item->parent); + + if (item->parent->parent != NULL) + new_path = g_strconcat(parent_path, ".sbd", NULL); + else + new_path = g_strdup(parent_path); + g_free(parent_path); + + if (!is_dir_exist(new_path)) + make_dir_hier(new_path); + g_free(new_path); + + } + + return path; +} /**********************************************************/ @@ -113,9 +177,7 @@ static gboolean mbox_fcntl_unlock_file(FILE * fp) static gboolean mbox_file_unlock_file(gchar * base) { - gchar *lockfile, *locklink; - gint retry = 0; - FILE *lockfp; + gchar *lockfile; lockfile = g_strdup_printf("%s.lock", base); unlink(lockfile); @@ -130,7 +192,7 @@ static gboolean mbox_lockread_file(FILE * fp, gchar * base) result = mbox_fcntl_lockread_file(fp); if (!result) { - if (result = mbox_file_lock_file(base)) { + if ((result = mbox_file_lock_file(base)) == TRUE) { file_lock = g_slist_append(file_lock, g_strdup(base)); debug_print("lockfile lock %s.\n", base); } @@ -149,7 +211,7 @@ static gboolean mbox_lockwrite_file(FILE * fp, gchar * base) result = mbox_fcntl_lockwrite_file(fp); if (!result) { - if (result = mbox_file_lock_file(base)) { + if ((result = mbox_file_lock_file(base)) == TRUE) { file_lock = g_slist_append(file_lock, g_strdup(base)); debug_print("lockfile lock %s.\n", base); } @@ -164,7 +226,7 @@ static gboolean mbox_lockwrite_file(FILE * fp, gchar * base) static gboolean mbox_unlock_file(FILE * fp, gchar * base) { - gboolean result; + gboolean result = FALSE; GSList * l; gboolean unlocked = FALSE; @@ -176,12 +238,15 @@ static gboolean mbox_unlock_file(FILE * fp, gchar * base) g_free(data); result = mbox_file_unlock_file(base); unlocked = TRUE; + debug_print("lockfile unlock - %s.\n", base); break; } } - if (!unlocked) + if (!unlocked) { result = mbox_fcntl_unlock_file(fp); + debug_print("fcntl unlock - %s.\n", base); + } return result; } @@ -208,9 +273,9 @@ static int mailfile_error = MAILFILE_ERROR_NO_ERROR; #define STATE_MEM_ERROR 0x006 #define STATE_TEXT_BEGIN 0x007 -#define STATE_MASK 0x0FF // filter state from functions +#define STATE_MASK 0x0FF /* filter state from functions */ -#define STATE_RESTORE_POS 0x100 // go back while reading +#define STATE_RESTORE_POS 0x100 /* go back while reading */ typedef struct _mailfile mailfile; @@ -224,7 +289,6 @@ struct _mailfile struct _message { int msgnum; - int deleted; int offset; int header; int content; @@ -233,6 +297,7 @@ struct _message gchar * messageid; gchar * fromspace; MsgFlags flags; + MsgFlags old_flags; gboolean fetched; }; @@ -270,7 +335,7 @@ static mailfile * mailfile_init_from_file(FILE * f, gchar * filename) { int state; GList * msg_list = NULL; - char * r; + char * r = NULL; char s[256]; int lastpos = 0; int former_pos = 0; @@ -281,6 +346,7 @@ static mailfile * mailfile_init_from_file(FILE * f, gchar * filename) state = STATE_BEGIN; + while (state != STATE_END_OF_FILE) { if ((state & STATE_RESTORE_POS) == 0) { former_pos = lastpos; @@ -313,12 +379,13 @@ static mailfile * mailfile_init_from_file(FILE * f, gchar * filename) data->header = lastpos; data->end = 0; data->content = 0; - data->deleted = 0; data->messageid = NULL; data->fromspace = NULL; data->flags = -1; + data->old_flags = -1; data->fetched = FALSE; - msg_list = g_list_append(msg_list, (gpointer) data); + msg_list = g_list_append(msg_list, + (gpointer) data); } else state = STATE_BEGIN; @@ -335,15 +402,15 @@ static mailfile * mailfile_init_from_file(FILE * f, gchar * filename) break; case STATE_TEXT_BEGIN: + data->content = lastpos; if (r == NULL) state = STATE_END; else if (startFrom(s)) { - data->content = lastpos; - state = STATE_END | STATE_RESTORE_POS; } - else + else { state = STATE_TEXT_READ; + } break; case STATE_FROM_READ: @@ -364,8 +431,9 @@ static mailfile * mailfile_init_from_file(FILE * f, gchar * filename) state = STATE_END; else if (startSpace(s)) state = STATE_FIELD_READ; - else if (startEmpty(s)) + else if (startEmpty(s)) { state = STATE_TEXT_BEGIN; + } else state = STATE_FIELD_READ; break; @@ -373,10 +441,7 @@ static mailfile * mailfile_init_from_file(FILE * f, gchar * filename) if ((state & STATE_MASK) == STATE_END) { state = STATE_BEGIN | (state & STATE_RESTORE_POS); - if (state & STATE_RESTORE_POS) - data->end = former_pos; - else - data->end = lastpos; + data->end = lastpos; } if (ignore_next) { @@ -396,7 +461,7 @@ static mailfile * mailfile_init_from_file(FILE * f, gchar * filename) return NULL; } - mf->msg_list = msg_list; + mf->msg_list = g_list_first(msg_list); mf->filename = g_strdup(filename); mf->count = msgnum; @@ -577,13 +642,42 @@ static int mailfile_find_deleted(mailfile f, char * filename) struct _mboxcache { gchar * filename; mailfile * mf; + GPtrArray * tab_mf; gint mtime; + gboolean modification; }; typedef struct _mboxcache mboxcache; static GHashTable * mbox_cache_table = NULL; -static mboxcache * current_mbox = NULL; + +static MsgInfo *mbox_parse_msg(FILE * fp, struct _message * msg, + FolderItem *item) +{ + MsgInfo *msginfo; + MsgFlags 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); + } else if (item->stype == F_DRAFT) { + MSG_SET_FLAGS(flags, MSG_DRAFT); + } + } + + msginfo = procheader_file_parse(fp, flags, FALSE); + + if (!msginfo) return NULL; + + if (item != NULL) { + msginfo->msgnum = msg->msgnum; + msginfo->folder = item; + } + + return msginfo; +} static void mbox_cache_init() { @@ -597,16 +691,62 @@ static void mbox_cache_done() static void mbox_cache_free_mbox(mboxcache * cache) { + g_hash_table_remove(mbox_cache_table, cache->filename); + + if (cache->mf) + mailfile_done(cache->mf); + if (cache->tab_mf) + g_ptr_array_free(cache->tab_mf, FALSE); if (cache->filename) g_free(cache->filename); g_free(cache); } +static void mbox_cache_get_msginfo_from_file(FILE * fp, GList * msg_list) +{ + GList * l; + MsgInfo * msginfo; + + for(l = msg_list ; l != NULL ; l = g_list_next(l)) { + struct _message * msg; + + msg = (struct _message *) l->data; + + fseek(fp, msg->header, SEEK_SET); + msginfo = mbox_parse_msg(fp, msg, NULL); + if (msginfo) { + if (msginfo->msgid) + msg->messageid = + g_strdup(msginfo->msgid); + if (msginfo->fromspace) + msg->fromspace = + g_strdup(msginfo->fromspace); + msg->flags = msginfo->flags; + msg->old_flags = msginfo->flags; + + procmsg_msginfo_free(msginfo); + } + } +} + +static void mbox_cache_get_msginfo(gchar * filename, GList * msg_list) +{ + FILE * fp; + + fp = fopen(filename, "r"); + if (fp == NULL) + return; + + mbox_cache_get_msginfo_from_file(fp, msg_list); + fclose(fp); +} + static mboxcache * mbox_cache_read_mbox(gchar * filename) { mboxcache * cache; struct stat s; mailfile * mf; + GList * l; if (stat(filename, &s) < 0) return NULL; @@ -620,6 +760,15 @@ static mboxcache * mbox_cache_read_mbox(gchar * filename) cache->mtime = s.st_mtime; cache->mf = mf; cache->filename = g_strdup(filename); + cache->modification = FALSE; + + cache->tab_mf = g_ptr_array_new(); + for(l = mf->msg_list ; l != NULL ; l = g_list_next(l)) + g_ptr_array_add(cache->tab_mf, l->data); + + mbox_cache_get_msginfo(filename, mf->msg_list); + + debug_print(_("read mbox - %s\n"), filename); return cache; } @@ -629,6 +778,7 @@ static mboxcache * mbox_cache_read_mbox_from_file(FILE * fp, gchar * filename) mboxcache * cache; struct stat s; mailfile * mf; + GList * l; if (stat(filename, &s) < 0) return NULL; @@ -643,15 +793,23 @@ static mboxcache * mbox_cache_read_mbox_from_file(FILE * fp, gchar * filename) cache->mf = mf; cache->filename = g_strdup(filename); + cache->tab_mf = g_ptr_array_new(); + for(l = mf->msg_list ; l != NULL ; l = g_list_next(l)) + g_ptr_array_add(cache->tab_mf, l->data); + + mbox_cache_get_msginfo_from_file(fp, mf->msg_list); + + debug_print(_("read mbox from file - %s\n"), filename); + return cache; } -static void mbox_cache_insert_mbox(gchar * filename, mboxcache * data) +static void mbox_cache_insert_mbox(mboxcache * data) { if (mbox_cache_table == NULL) mbox_cache_init(); - g_hash_table_insert(mbox_cache_table, filename, data); + g_hash_table_insert(mbox_cache_table, data->filename, data); } static mboxcache * mbox_cache_get_mbox(gchar * filename) @@ -700,43 +858,44 @@ static GList * mbox_cache_get_msg_list(gchar * filename) return cache->mf->msg_list; } -static void mbox_cache_synchronize_lists(GList * msg_new_list, - GList * msg_old_list) +static void mbox_cache_synchronize_lists(GList * old_msg_list, + GList * new_msg_list) { - struct _message * msg_new; - struct _message * msg_old; - GList * l_new; - GList * l_old; + GList * l; + GList * l2; - // could be improved with a hash table - for(l_old = msg_old_list ; l_old != NULL ; - l_old = g_list_next(l_old)) { - msg_old = (struct _message *) l_old->data; - - if ((msg_old->messageid == NULL) || - (msg_old->fromspace == NULL)) + for(l2 = old_msg_list ; l2 != NULL ; l2 = g_list_next(l2)) { + struct _message * msg2 = l2->data; + + printf("lili %p\n", msg2); + + printf("lili %p\n", msg2->messageid); + + if ((msg2->messageid == NULL) || + (msg2->fromspace == NULL)) continue; - - for(l_new = msg_new_list ; l_new != NULL ; - l_new = g_list_next(l_new)) { - msg_new = (struct _message *) l_new->data; + + for(l = new_msg_list ; l != NULL ; l = g_list_next(l)) { + struct _message * msg = l->data; - if ((msg_new->messageid == NULL) || - (msg_new->fromspace == NULL)) + if ((msg->messageid == NULL) || + (msg->fromspace == NULL)) continue; - - if (!strcmp(msg_new->messageid, msg_old->messageid) && - !strcmp(msg_new->fromspace, msg_old->fromspace)) { - // copy flags - msg_new->deleted = msg_old->deleted; - msg_new->flags = msg_old->flags; - break; + + 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)) { + msg->flags = msg2->flags; + break; + } } } } } -static void mbox_cache_synchronize(gchar * filename) +static void mbox_cache_synchronize(gchar * filename, gboolean sync) { mboxcache * new_cache; mboxcache * old_cache; @@ -755,26 +914,61 @@ static void mbox_cache_synchronize(gchar * filename) } if (scan_new) { + GList * l; + + /* + if (strstr(filename, "trash") == 0) + printf("old_cache: %p %s\n", old_cache, filename); + if (old_cache) { + printf("begin old\n"); + for(l = old_cache->mf->msg_list ; l != NULL ; + l = g_list_next(l)) { + struct _message * msg = l->data; + printf("%p\n", msg); + } + printf("end old\n"); + } + */ + new_cache = mbox_cache_read_mbox(filename); - - if (new_cache == NULL) { - if (old_cache != NULL) - mbox_cache_free_mbox(old_cache); + + /* + if (strstr(filename, "trash") == 0) + printf("new_cache: %p %s\n", new_cache, filename); + if (new_cache) { + printf("begin new\n"); + for(l = new_cache->mf->msg_list ; l != NULL ; + l = g_list_next(l)) { + struct _message * msg = l->data; + printf("%p\n", msg); + } + printf("end new\n"); + } + */ + + if (!new_cache) return; - } - if (old_cache != NULL) { - if ((old_cache->mf != NULL) && - (new_cache->mf != NULL)) - mbox_cache_synchronize_lists(new_cache->mf->msg_list, old_cache->mf->msg_list); + if (sync && new_cache && old_cache) + mbox_cache_synchronize_lists(old_cache->mf->msg_list, + new_cache->mf->msg_list); + + if (old_cache != NULL) mbox_cache_free_mbox(old_cache); + + if (new_cache) { + mbox_cache_insert_mbox(new_cache); + /* + printf("insert %p %s\n", new_cache, new_cache->filename); + printf("inserted %s %p\n", filename, + mbox_cache_get_mbox(filename)); + */ } - - mbox_cache_insert_mbox(filename, new_cache); } } -static void mbox_cache_synchronize_from_file(FILE * fp, gchar * filename) +static void mbox_cache_synchronize_from_file(FILE * fp, gchar * filename, + gboolean sync) { mboxcache * new_cache; mboxcache * old_cache; @@ -792,34 +986,76 @@ static void mbox_cache_synchronize_from_file(FILE * fp, gchar * filename) } } + if (scan_new) { - new_cache = mbox_cache_read_mbox_from_file(fp, filename); + + /* + GList * l; + + if (strstr(filename, "trash") == 0) + printf("old_cache: %p %s\n", old_cache, filename); + + if (old_cache) { + printf("begin old\n"); + for(l = old_cache->mf->msg_list ; l != NULL ; + l = g_list_next(l)) { + struct _message * msg = l->data; + printf("%p\n", msg); + } + printf("end old\n"); + } + */ - if (new_cache == NULL) { - if (old_cache != NULL) - mbox_cache_free_mbox(old_cache); + new_cache = mbox_cache_read_mbox_from_file(fp, filename); + + /* + if (strstr(filename, "trash") == 0) + printf("new_cache: %p %s\n", new_cache, filename); + + if (new_cache) { + printf("begin new\n"); + for(l = new_cache->mf->msg_list ; l != NULL ; + l = g_list_next(l)) { + struct _message * msg = l->data; + printf("%p\n", msg); + } + printf("end new\n"); + } + */ + + if (!new_cache) return; - } - if (old_cache != NULL) { - if ((old_cache->mf != NULL) && - (new_cache->mf != NULL)) - mbox_cache_synchronize_lists(new_cache->mf->msg_list, old_cache->mf->msg_list); + if (sync && new_cache && old_cache) + mbox_cache_synchronize_lists(old_cache->mf->msg_list, + new_cache->mf->msg_list); + + if (old_cache != NULL) mbox_cache_free_mbox(old_cache); + + if (new_cache) { + mbox_cache_insert_mbox(new_cache); + /* + printf("insert %p %s\n", new_cache, new_cache->filename); + printf("inserted %s %p\n", filename, + mbox_cache_get_mbox(filename)); + */ } - - mbox_cache_insert_mbox(filename, new_cache); } } gboolean mbox_cache_msg_fetched(gchar * filename, gint num) { - GList * msg_list; struct _message * msg; + mboxcache * cache; + + cache = mbox_cache_get_mbox(filename); - msg_list = mbox_cache_get_msg_list(filename); - msg = (struct _message *) g_list_nth_data(msg_list, num - 1); + if (cache == NULL) + return FALSE; + msg = (struct _message *) g_ptr_array_index(cache->tab_mf, + num - 1); if (msg == NULL) return FALSE; @@ -828,66 +1064,51 @@ gboolean mbox_cache_msg_fetched(gchar * filename, gint num) void mbox_cache_msg_set_fetched(gchar * filename, gint num) { - GList * msg_list; struct _message * msg; + mboxcache * cache; - msg_list = mbox_cache_get_msg_list(filename); - if ((msg = (struct _message *) g_list_nth_data(msg_list, num - 1)) - == NULL) - return; - msg->fetched = TRUE; -} + cache = mbox_cache_get_mbox(filename); + if (cache == NULL) + return; -/**********************************************************/ -/* */ -/* mbox operations */ -/* */ -/**********************************************************/ + msg = (struct _message *) g_ptr_array_index(cache->tab_mf, + num - 1); + if (msg == NULL) + return; + msg->fetched = TRUE; +} -static MsgInfo *mbox_parse_msg(FILE * fp, gint msgnum, FolderItem *item) +struct _message * mbox_cache_get_msg(gchar * filename, gint num) { - struct stat s; - MsgInfo *msginfo; - MsgFlags flags = MSG_NEW|MSG_UNREAD; + mboxcache * cache; - g_return_val_if_fail(item != NULL, NULL); - g_return_val_if_fail(fp != NULL, NULL); + cache = mbox_cache_get_mbox(filename); - if (item->stype == F_QUEUE) { - MSG_SET_FLAGS(flags, MSG_QUEUED); - } else if (item->stype == F_DRAFT) { - MSG_SET_FLAGS(flags, MSG_DRAFT); + if (cache == NULL) { + return NULL; } - msginfo = procheader_file_parse(fp, flags, FALSE); - - if (!msginfo) return NULL; + return (struct _message *) g_ptr_array_index(cache->tab_mf, + num - 1); +} - msginfo->msgnum = msgnum; - msginfo->folder = item; - if (stat(item->path, &s) < 0) { - FILE_OP_ERROR(item->path, "stat"); - msginfo->size = 0; - msginfo->mtime = 0; - } else { - msginfo->size = s.st_size; - msginfo->mtime = s.st_mtime; - } +/**********************************************************/ +/* */ +/* mbox operations */ +/* */ +/**********************************************************/ - return msginfo; -} GSList *mbox_get_msg_list(Folder *folder, FolderItem *item, gboolean use_cache) { GSList *mlist; - GHashTable *msg_table; - MsgFlags flags = MSG_NEW|MSG_UNREAD; MsgInfo * msginfo; GList * l; FILE * fp; + gchar * mbox_path; #ifdef MEASURE_TIME struct timeval tv_before, tv_after, tv_result; @@ -897,44 +1118,54 @@ GSList *mbox_get_msg_list(Folder *folder, FolderItem *item, gboolean use_cache) mlist = NULL; - fp = fopen(item->path, "r"); + mbox_path = mbox_folder_get_path(item); - mbox_lockread_file(fp, item->path); + if (mbox_path == NULL) + return NULL; - mbox_cache_synchronize_from_file(fp, item->path); + mbox_purge_deleted(mbox_path); - if (mbox_cache_get_mbox(item->path) == NULL) { - g_warning(_("parsing of %s failed.\n"), item->path); - mbox_unlock_file(fp, item->path); - fclose(fp); + fp = fopen(mbox_path, "r"); + + if (fp == NULL) { + g_free(mbox_path); return NULL; } - for(l = mbox_cache_get_msg_list(item->path) ; l != 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->deleted) { + if (msg->flags == -1 || !MSG_IS_REALLY_DELETED(msg->flags)) { fseek(fp, msg->header, SEEK_SET); - msginfo = mbox_parse_msg(fp, msg->msgnum, item); - if (msginfo) { - if (msginfo->msgid) - msg->messageid = - g_strdup(msginfo->msgid); - if (msginfo->fromspace) - msg->fromspace = - g_strdup(msginfo->fromspace); - msginfo->data = msg; - } + + msginfo = mbox_parse_msg(fp, msg, item); + if (msg->flags != -1) msginfo->flags = msg->flags; + else { + msg->old_flags = msginfo->flags; + msg->flags = msginfo->flags; + } + mlist = g_slist_append(mlist, msginfo); } + else { + msg->flags = MSG_REALLY_DELETED; + } } - mbox_unlock_file(fp, item->path); + mbox_unlock_file(fp, mbox_path); + + g_free(mbox_path); fclose(fp); @@ -943,13 +1174,13 @@ GSList *mbox_get_msg_list(Folder *folder, FolderItem *item, gboolean use_cache) timersub(&tv_after, &tv_before, &tv_result); g_print("mbox_get_msg_list: %s: elapsed time: %ld.%06ld sec\n", - item->path, tv_result.tv_sec, tv_result.tv_usec); + mbox_path, tv_result.tv_sec, tv_result.tv_usec); #endif return mlist; } -static gboolean mbox_extract_msg(gchar * mbox_filename, gint msgnum, +static gboolean mbox_extract_msg(FolderItem * item, gint msgnum, gchar * dest_filename) { struct _message * msg; @@ -959,32 +1190,40 @@ static gboolean mbox_extract_msg(gchar * mbox_filename, gint msgnum, FILE * src; FILE * dest; gboolean err; - GList * msg_list; + /* GList * msg_list;*/ gboolean already_fetched; + gchar * mbox_path; + + mbox_path = mbox_folder_get_path(item); + + if (mbox_path == NULL) + return FALSE; - src = fopen(mbox_filename, "r"); - if (src == NULL) + src = fopen(mbox_path, "r"); + if (src == NULL) { + g_free(mbox_path); return FALSE; + } - mbox_lockread_file(src, mbox_filename); + mbox_lockread_file(src, mbox_path); - mbox_cache_synchronize_from_file(src, mbox_filename); + mbox_cache_synchronize_from_file(src, mbox_path, TRUE); - already_fetched = mbox_cache_msg_fetched(mbox_filename, msgnum); + already_fetched = mbox_cache_msg_fetched(mbox_path, msgnum); if (already_fetched) { - mbox_unlock_file(src, mbox_filename); + mbox_unlock_file(src, mbox_path); fclose(src); + g_free(mbox_path); return TRUE; } - msg_list = mbox_cache_get_msg_list(mbox_filename); - - msg = (struct _message *) g_list_nth_data(msg_list, msgnum - 1); + msg = mbox_cache_get_msg(mbox_path, msgnum); if (msg == NULL) { - mbox_unlock_file(src, mbox_filename); + mbox_unlock_file(src, mbox_path); fclose(src); + g_free(mbox_path); return FALSE; } @@ -997,8 +1236,9 @@ static gboolean mbox_extract_msg(gchar * mbox_filename, gint msgnum, dest = fopen(dest_filename, "w"); if (dest == NULL) { - mbox_unlock_file(src, mbox_filename); + mbox_unlock_file(src, mbox_path); fclose(src); + g_free(mbox_path); return FALSE; } @@ -1008,34 +1248,37 @@ static gboolean mbox_extract_msg(gchar * mbox_filename, gint msgnum, } if (!mbox_write_data(src, dest, dest_filename, size)) { - mbox_unlock_file(src, mbox_filename); + mbox_unlock_file(src, mbox_path); fclose(dest); fclose(src); unlink(dest_filename); + g_free(mbox_path); return FALSE; } err = FALSE; if (ferror(src)) { - FILE_OP_ERROR(mbox_filename, "fread"); + FILE_OP_ERROR(mbox_path, "fread"); err = TRUE; } - mbox_cache_msg_set_fetched(mbox_filename, msgnum); + mbox_cache_msg_set_fetched(mbox_path, msgnum); if (fclose(dest) == -1) { FILE_OP_ERROR(dest_filename, "fclose"); - return FALSE; + err = TRUE; } - mbox_unlock_file(src, mbox_filename); + mbox_unlock_file(src, mbox_path); if (fclose(src) == -1) { - FILE_OP_ERROR(mbox_filename, "fclose"); + FILE_OP_ERROR(mbox_path, "fclose"); err = TRUE; } + g_free(mbox_path); + if (err) { unlink(dest_filename); return FALSE; @@ -1050,9 +1293,7 @@ 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)) @@ -1062,7 +1303,7 @@ gchar *mbox_fetch_msg(Folder *folder, FolderItem *item, gint num) g_free(path); - if (!mbox_extract_msg(item->path, num, filename)) { + if (!mbox_extract_msg(item, num, filename)) { g_free(filename); return NULL; } @@ -1079,6 +1320,8 @@ gint mbox_add_msg(Folder *folder, FolderItem *dest, const gchar *file, gint old_size; gint n_read; gboolean err; + gchar * mbox_path; + gchar from_line[MSGBUFSIZE]; if (dest->last_num < 0) { mbox_scan_folder(folder, dest); @@ -1090,38 +1333,71 @@ gint mbox_add_msg(Folder *folder, FolderItem *dest, const gchar *file, return -1; } - dest_fp = fopen(dest->path, "a"); + mbox_path = mbox_folder_get_path(dest); + if (mbox_path == NULL) + return -1; + + dest_fp = fopen(mbox_path, "a"); if (dest_fp == NULL) { fclose(src_fp); + g_free(mbox_path); return -1; } old_size = ftell(dest_fp); - mbox_lockwrite_file(dest_fp, dest->path); + mbox_lockwrite_file(dest_fp, mbox_path); + + if (fgets(from_line, sizeof(from_line), src_fp) == NULL) { + mbox_unlock_file(dest_fp, mbox_path); + g_warning(_("unvalid file - %s.\n"), file); + fclose(dest_fp); + fclose(src_fp); + g_free(mbox_path); + return -1; + } + if (strncmp(from_line, "From ", 5) != 0) { + struct stat s; + + if (stat(file, &s) < 0) { + mbox_unlock_file(dest_fp, mbox_path); + g_warning(_("unvalid file - %s.\n"), file); + fclose(dest_fp); + fclose(src_fp); + g_free(mbox_path); + return -1; + } + + fprintf(dest_fp, "From - %s", ctime(&s.st_mtime)); + } + + fputs(from_line, dest_fp); + while (1) { n_read = fread(buf, 1, sizeof(buf), src_fp); - if (n_read < sizeof(buf) && ferror(src_fp)) + if ((n_read < (gint) sizeof(buf)) && ferror(src_fp)) break; if (fwrite(buf, n_read, 1, dest_fp) < 1) { - g_warning(_("writing to %s failed.\n"), dest->path); + mbox_unlock_file(dest_fp, mbox_path); + g_warning(_("writing to %s failed.\n"), mbox_path); ftruncate(fileno(dest_fp), old_size); fclose(dest_fp); fclose(src_fp); + g_free(mbox_path); return -1; } - if (n_read < sizeof(buf)) + if (n_read < (gint) sizeof(buf)) break; } err = FALSE; if (ferror(src_fp)) { - FILE_OP_ERROR(dest->path, "fread"); + FILE_OP_ERROR(mbox_path, "fread"); } - mbox_unlock_file(src_fp, dest->path); + mbox_unlock_file(dest_fp, mbox_path); if (fclose(src_fp) == -1) { FILE_OP_ERROR(file, "fclose"); @@ -1129,12 +1405,14 @@ gint mbox_add_msg(Folder *folder, FolderItem *dest, const gchar *file, } if (fclose(dest_fp) == -1) { - FILE_OP_ERROR(dest->path, "fclose"); + FILE_OP_ERROR(mbox_path, "fclose"); + g_free(mbox_path); return -1; } if (err) { ftruncate(fileno(dest_fp), old_size); + g_free(mbox_path); return -1; } @@ -1143,6 +1421,8 @@ gint mbox_add_msg(Folder *folder, FolderItem *dest, const gchar *file, FILE_OP_ERROR(file, "unlink"); } + g_free(mbox_path); + dest->last_num++; return dest->last_num; @@ -1151,22 +1431,20 @@ gint mbox_add_msg(Folder *folder, FolderItem *dest, const gchar *file, gint mbox_remove_msg(Folder *folder, FolderItem *item, gint num) { struct _message * msg; - GList * msg_list; + gchar * mbox_path; - mbox_cache_synchronize(item->path); + mbox_path = mbox_folder_get_path(item); + if (mbox_path == NULL) + return -1; - msg_list = mbox_cache_get_msg_list(item->path); + mbox_cache_synchronize(mbox_path, TRUE); - msg = (struct _message *) g_list_nth_data(msg_list, - num - 1); - msg->deleted = 1; + msg = mbox_cache_get_msg(mbox_path, num); - /* - if (!mbox_rewrite(item->path)) { - printf("rewrite %s\n", item->path); - return -1; - } - */ + g_free(mbox_path); + + if (msg != NULL) + MSG_SET_FLAGS(msg->flags, MSG_REALLY_DELETED); return 0; } @@ -1174,128 +1452,257 @@ gint mbox_remove_msg(Folder *folder, FolderItem *item, gint num) gint mbox_remove_all_msg(Folder *folder, FolderItem *item) { FILE * fp; + gchar * mbox_path; + + mbox_path = mbox_folder_get_path(item); + if (mbox_path == NULL) + return -1; - fp = fopen(item->path, "w"); + fp = fopen(mbox_path, "w"); if (fp == NULL) { + g_free(mbox_path); return -1; } fclose(fp); + g_free(mbox_path); + return 0; } +/* gint mbox_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo) { - /* + gchar * filename; + gint msgnum; - mbox_cache_synchronize(item->path); + filename = mbox_fetch_msg(folder, msginfo->folder, msginfo->msgnum); + if (filename == NULL) + return -1; - size = msg->end - msg->offset; + msgnum = mbox_add_msg(folder, dest, filename, TRUE); - src = fopen(mbox_filename, "r"); - if (src == NULL) - return FALSE; - fseek(src, msg->offset, SEEK_SET); + if (msgnum != -1) { + MSG_SET_FLAGS(msginfo->flags, MSG_REALLY_DELETED); + mbox_change_flags(folder, msginfo->folder, msginfo); + } - mbox_lockread_file(src, mbox_filename); + return msgnum; +} - dest = fopen(dest_filename, "a"); - if (dest == NULL) { - fclose(src); - return FALSE; - } +gint mbox_move_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist) +{ + GSList * l; + gchar * mbox_path = NULL; - if (change_file_mode_rw(dest, dest_filename) < 0) { - FILE_OP_ERROR(dest_filename, "chmod"); - g_warning(_("can't change file mode\n")); + for(l = msglist ; l != NULL ; l = g_slist_next(l)) { + MsgInfo * msginfo = (MsgInfo *) l->data; + + if (msginfo->folder && mbox_path == NULL) + mbox_path = mbox_folder_get_path(msginfo->folder); + + mbox_move_msg(folder, dest, msginfo); } - if (!mbox_write_data(src, dest, dest_filename, size)) { - fclose(dest); - fclose(src); - unlink(dest_filename); - return FALSE; + if (mbox_path) { + mbox_cache_synchronize(mbox_path); + g_free(mbox_path); } - - return -1; - */ + + mbox_path = mbox_folder_get_path(dest); + mbox_cache_synchronize(mbox_path); + g_free(mbox_path); + + return dest->last_num; +} +*/ + +/* +gint mbox_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo) +{ gchar * filename; + gint msgnum; filename = mbox_fetch_msg(folder, msginfo->folder, msginfo->msgnum); if (filename == NULL) return -1; - ((struct _message *) msginfo->data)->deleted = TRUE; + msgnum = mbox_add_msg(folder, dest, filename, FALSE); - return mbox_add_msg(folder, dest, filename, TRUE); + return msgnum; } -gint mbox_move_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist) +gint mbox_copy_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist) { GSList * l; - gchar * path = NULL; + gchar * mbox_path = NULL; for(l = msglist ; l != NULL ; l = g_slist_next(l)) { MsgInfo * msginfo = (MsgInfo *) l->data; - if (msginfo->folder) - path = msginfo->folder->path; + if (msginfo->folder && mbox_path == NULL) + mbox_path = mbox_folder_get_path(msginfo->folder); - mbox_move_msg(folder, dest, msginfo); + mbox_copy_msg(folder, dest, msginfo); } - if (path) { - mbox_rewrite(path); - printf("fini\n"); - mbox_cache_synchronize(path); + if (mbox_path) { + mbox_cache_synchronize(mbox_path); + g_free(mbox_path); } - mbox_cache_synchronize(dest->path); + + mbox_path = mbox_folder_get_path(dest); + mbox_cache_synchronize(mbox_path); + g_free(mbox_path); return dest->last_num; } +*/ -void mbox_scan_folder(Folder *folder, FolderItem *item) +struct _copy_flags_info { - gchar *path; - struct stat s; - gint max = 0; gint num; + MsgFlags flags; +}; + +typedef struct _copy_flags_info CopyFlagsInfo; + +GSList * copy_flags_data = NULL; + +gint mbox_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo) +{ + Folder * src_folder; + gchar * filename; + gint num; + gchar * destdir; + gchar * mbox_path; + struct _message * msg; + CopyFlagsInfo * flags_info; + + src_folder = msginfo->folder->folder; + + g_return_val_if_fail(src_folder->fetch_msg != NULL, -1); + + /* + mbox_path = mbox_folder_get_path(msginfo->folder); + mbox_rewrite(mbox_path); + g_free(mbox_path); + */ + + filename = src_folder->fetch_msg(src_folder, + msginfo->folder, + msginfo->msgnum); + if (filename == NULL) + return -1; + + num = folder->add_msg(folder, dest, filename, FALSE); + + /* + mbox_path = mbox_folder_get_path(dest); + msg = mbox_cache_get_msg(mbox_path, num); + if (msg != NULL) + msg->flags = msginfo->flags; + g_free(mbox_path); + */ + + flags_info = g_new0(CopyFlagsInfo, 1); + flags_info->num = num; + flags_info->flags = msginfo->flags; + copy_flags_data = g_slist_append(copy_flags_data, flags_info); + + return num; +} + +void mbox_finished_copy(Folder *folder, FolderItem *dest) +{ + gchar * mbox_path; + GSList * l; + mboxcache * cache; + + mbox_path = mbox_folder_get_path(dest); + if (mbox_path == NULL) + return; + + mbox_cache_synchronize(mbox_path, TRUE); + + for(l = copy_flags_data ; l != NULL ; l = g_slist_next(l)) { + CopyFlagsInfo * flags_info = l->data; + struct _message * msg; + + msg = mbox_cache_get_msg(mbox_path, flags_info->num); + if (msg != NULL) + msg->flags = flags_info->flags; + g_free(flags_info); + } + + if (copy_flags_data != NULL) { + cache = mbox_cache_get_mbox(mbox_path); + cache->modification = TRUE; + } + + g_slist_free(copy_flags_data); + copy_flags_data = NULL; + + mbox_rewrite(mbox_path); + + g_free(mbox_path); +} + +void mbox_scan_folder(Folder *folder, FolderItem *item) +{ + gchar *mbox_path; gint n_msg; mboxcache * cached; + GList * l; + + mbox_path = mbox_folder_get_path(item); + if (mbox_path == NULL) + return; - mbox_cache_synchronize(item->path); + mbox_cache_synchronize(mbox_path, TRUE); - cached = mbox_cache_get_mbox(item->path); + cached = mbox_cache_get_mbox(mbox_path); if (cached == NULL) { item->new = 0; item->unread = 0; item->total = 0; item->last_num = 0; + g_free(mbox_path); return; } - n_msg = mbox_cache_get_count(item->path); + n_msg = mbox_cache_get_count(mbox_path); - if (n_msg == 0) + if (n_msg == 0) { item->new = item->unread = item->total = 0; + } else { - gint new, unread, total; - - // procmsg_get_mark_sum(".", &new, &unread, &total); - if (n_msg > total) { - new += n_msg - total; - unread += n_msg - total; + gint new = 0; + gint unread = 0; + gint total = 0; + + for(l = mbox_cache_get_msg_list(mbox_path) ; l != NULL ; + l = g_list_next(l)) { + struct _message * msg = (struct _message *) l->data; + if (!MSG_IS_REALLY_DELETED(msg->flags)) + total ++; + if (MSG_IS_NEW(msg->flags)) + new ++; + if (MSG_IS_UNREAD(msg->flags)) + unread ++; } + item->new = new; item->unread = unread; - item->total = n_msg; + item->total = total; } - debug_print(_("Last number in dir %s = %d\n"), item->path, + debug_print(_("Last number in dir %s = %d\n"), mbox_path, item->total); - item->last_num = item->total; + item->last_num = n_msg; + g_free(mbox_path); } gchar * mbox_get_virtual_path(FolderItem * item) @@ -1333,12 +1740,13 @@ static gboolean mbox_write_data(FILE * mbox_fp, FILE * new_fp, pos = 0; while (pos < size) { - if ((size - pos) > sizeof(buf)) + if ((size - pos) > (gint) sizeof(buf)) max = sizeof(buf); else max = (size - pos); n_read = fread(buf, 1, max, mbox_fp); + if (n_read < max && ferror(mbox_fp)) { return FALSE; } @@ -1357,18 +1765,19 @@ static gboolean mbox_write_data(FILE * mbox_fp, FILE * new_fp, } static gboolean mbox_write_message(FILE * mbox_fp, FILE * new_fp, - gchar * new_filename, - struct _message * msg) + gchar * new_filename, + struct _message * msg) { - GSList * headers; - GSList * cur; gint size; + GPtrArray * headers; + gint i; fseek(mbox_fp, msg->header, SEEK_SET); - headers = procheader_get_header_list(mbox_fp); - for(cur = headers ; cur != NULL ; - cur = g_slist_next(cur)) { - Header * h = (Header *) cur->data; + + headers = procheader_get_header_array_asis(mbox_fp); + + for (i = 0; i < (gint) headers->len; i++) { + Header * h = g_ptr_array_index(headers, i); if (!procheader_headername_equal(h->name, "Status") && @@ -1376,14 +1785,50 @@ static gboolean mbox_write_message(FILE * mbox_fp, FILE * new_fp, "X-Status")) { fwrite(h->name, strlen(h->name), 1, new_fp); - fwrite(" ", 1, 1, new_fp); + if (h->name[strlen(h->name) - 1] != ' ') + fwrite(" ", 1, 1, new_fp); fwrite(h->body, strlen(h->body), 1, new_fp); - fwrite("\r\n", 2, 1, new_fp); + fwrite("\n", 1, 1, new_fp); } + procheader_header_free(h); + g_ptr_array_remove_index(headers, i); + i--; } - fwrite("\r\n", 2, 1, new_fp); - + + g_ptr_array_free(headers, FALSE); + + if (msg->flags != -1) { + /* Status header */ + fwrite("Status: ", strlen("Status: "), 1, new_fp); + if (!MSG_IS_UNREAD(msg->flags)) + fwrite("R", 1, 1, new_fp); + fwrite("O", 1, 1, 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)) { + fwrite("X-Status: ", strlen("X-Status: "), 1, new_fp); + if (MSG_IS_REALLY_DELETED(msg->flags)) + fwrite("D", 1, 1, new_fp); /* really deleted */ + else { + if (MSG_IS_MARKED(msg->flags)) + fwrite("F", 1, 1, new_fp); + if (MSG_IS_DELETED(msg->flags)) + fwrite("d", 1, 1, new_fp); + if (MSG_IS_REPLIED(msg->flags)) + fwrite("r", 1, 1, new_fp); + if (MSG_IS_FORWARDED(msg->flags)) + fwrite("f", 1, 1, new_fp); + } + fwrite("\n", 1, 1, new_fp); + } + } + + fwrite("\n", 1, 1, new_fp); + size = msg->end - msg->content; fseek(mbox_fp, msg->content, SEEK_SET); @@ -1392,31 +1837,120 @@ static gboolean mbox_write_message(FILE * mbox_fp, FILE * new_fp, void mbox_update_mark(Folder * folder, FolderItem * item) { - GList * msg_list; - GList * l; + gchar * mbox_path; - /* - msg_list = mbox_cache_get_msg_list(item->path); - - for(l = msg_list ; l != NULL ; l = g_list_next(l)) { - struct _message * msg = (struct _message *) l->data; + mbox_path = mbox_folder_get_path(item); + if (mbox_path == NULL) + return; - if (msg->msginfo != NULL) { - msg->flags = msg->msginfo->flags & - MSG_PERMANENT_FLAG_MASK; - } - } - */ + mbox_rewrite(mbox_path); + g_free(mbox_path); } void mbox_change_flags(Folder * folder, FolderItem * item, MsgInfo * info) { - struct _message * msg = (struct _message *) info->data; + struct _message * msg; + mboxcache * cache; + gchar * mbox_path; + + mbox_path = mbox_folder_get_path(item); + if (mbox_path == NULL) + return; + + msg = mbox_cache_get_msg(mbox_path, info->msgnum); + + cache = mbox_cache_get_mbox(mbox_path); + + g_free(mbox_path); + + if ((msg == NULL) || (cache == NULL)) + return; msg->flags = info->flags; + + cache->modification = TRUE; } -gboolean mbox_rewrite(gchar * mbox) + +static gboolean mbox_rewrite(gchar * mbox) +{ + FILE * mbox_fp; + FILE * new_fp; + gchar * new; + GList * l; + gboolean result; + GList * msg_list; + gint count; + mboxcache * cache; + + msg_list = mbox_cache_get_msg_list(mbox); + + cache = mbox_cache_get_mbox(mbox); + if (cache == NULL) + return FALSE; + + if (!cache->modification) { + debug_print(_("no modification - %s\n"), mbox); + return FALSE; + } + + debug_print(_("save modification - %s\n"), mbox); + + mbox_fp = fopen(mbox, "r+"); + mbox_lockwrite_file(mbox_fp, mbox); + + mbox_cache_synchronize_from_file(mbox_fp, mbox, TRUE); + + new = g_strconcat(mbox, ".new", NULL); + new_fp = fopen(new, "w"); + + mbox_lockwrite_file(new_fp, new); + + result = TRUE; + + count = 0; + 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 (!mbox_write_message(mbox_fp, new_fp, new, msg)) { + result = FALSE; + break; + } + count ++; + } + + unlink(mbox); + + if (rename(new, mbox) == -1) { + g_warning(_("can't rename %s to %s\n"), new, mbox); + mbox_unlock_file(new_fp, new); + fclose(new_fp); + mbox_unlock_file(mbox_fp, mbox); + fclose(mbox_fp); + return -1; + } + + mbox_unlock_file(new_fp, new); + + fclose(new_fp); + + mbox_unlock_file(mbox_fp, mbox); + + fclose(mbox_fp); + + debug_print(_("%i messages written - %s\n"), count, mbox); + + cache = mbox_cache_get_mbox(mbox); + + if (cache != NULL) + cache->mtime = -1; + + mbox_cache_synchronize(mbox, FALSE); + + return result; +} + +static gboolean mbox_purge_deleted(gchar * mbox) { FILE * mbox_fp; FILE * new_fp; @@ -1425,25 +1959,31 @@ gboolean mbox_rewrite(gchar * mbox) gboolean result; gboolean modification = FALSE; GList * msg_list; + gint count; + + mbox_cache_synchronize(mbox, TRUE); 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->deleted) { - printf("modification\n"); + if (msg->flags != -1 && MSG_IS_REALLY_DELETED(msg->flags)) { modification = TRUE; break; } } - if (!modification) + if (!modification) { + debug_print(_("no deleted messages - %s\n"), mbox); return FALSE; + } + + debug_print(_("purge deleted messages - %s\n"), mbox); mbox_fp = fopen(mbox, "r+"); mbox_lockwrite_file(mbox_fp, mbox); - mbox_cache_synchronize_from_file(mbox_fp, mbox); + mbox_cache_synchronize_from_file(mbox_fp, mbox, TRUE); new = g_strconcat(mbox, ".new", NULL); new_fp = fopen(new, "w"); @@ -1452,20 +1992,22 @@ gboolean mbox_rewrite(gchar * mbox) result = TRUE; + count = 0; 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->deleted) + if (msg->flags == -1 || !MSG_IS_REALLY_DELETED(msg->flags)) { if (!mbox_write_message(mbox_fp, new_fp, new, msg)) { result = FALSE; break; } + count ++; + } } unlink(mbox); - g_warning(_("can't rename %s to %s\n"), new, mbox); - if (rename(new_fp, mbox) == -1) { + if (rename(new, mbox) == -1) { g_warning(_("can't rename %s to %s\n"), new, mbox); mbox_unlock_file(new_fp, new); fclose(new_fp); @@ -1481,5 +2023,162 @@ gboolean mbox_rewrite(gchar * mbox) mbox_unlock_file(mbox_fp, mbox); fclose(mbox_fp); + + debug_print(_("%i messages written - %s\n"), count, mbox); + + mbox_cache_synchronize(mbox, FALSE); + return result; } + +#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 (mkdir(dir, S_IRWXU) < 0) { \ + FILE_OP_ERROR(dir, "mkdir"); \ + return -1; \ + } \ + if (chmod(dir, S_IRWXU) < 0) \ + FILE_OP_ERROR(dir, "chmod"); \ + } \ +} + +gint mbox_create_tree(Folder *folder) +{ + gchar *rootpath; + + g_return_val_if_fail(folder != NULL, -1); + + CHDIR_RETURN_VAL_IF_FAIL(get_home_dir(), -1); + rootpath = LOCAL_FOLDER(folder)->rootpath; + MAKE_DIR_IF_NOT_EXIST(rootpath); + CHDIR_RETURN_VAL_IF_FAIL(rootpath, -1); + + return 0; +} + +#undef MAKE_DIR_IF_NOT_EXIST + +static gchar * mbox_get_new_path(FolderItem * parent, gchar * name) +{ + gchar * path; + + if (strchr(name, '/') == NULL) { + if (parent->path != NULL) + path = g_strconcat(parent->path, ".sbd", G_DIR_SEPARATOR_S, name, NULL); + else + path = g_strdup(name); + } + else + path = g_strdup(name); + + return path; +} + +static gchar * mbox_get_folderitem_name(gchar * name) +{ + gchar * foldername; + gchar * p; + + if ((p = strchr(name, '/')) == NULL) + foldername = g_strdup(name); + else { + gchar * newp = p; + + while (newp != NULL) { + newp = strchr(p, '/'); + if (newp != NULL) + p = newp + 1; + } + + foldername = g_strdup(p); + } + return foldername; +} + +FolderItem *mbox_create_folder(Folder *folder, FolderItem *parent, + const gchar *name) +{ + gchar * path; + FolderItem *new_item; + gchar * foldername; + + 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 = mbox_get_new_path(parent, (gchar *) name); + + foldername = mbox_get_folderitem_name((gchar *) name); + + new_item = folder_item_new(foldername, path); + folder_item_append(parent, new_item); + + if (!strcmp(name, "inbox")) { + new_item->stype = F_INBOX; + new_item->folder->inbox = new_item; + } else if (!strcmp(name, "outbox")) { + new_item->stype = F_OUTBOX; + new_item->folder->outbox = new_item; + } else if (!strcmp(name, "draft")) { + new_item->stype = F_DRAFT; + new_item->folder->draft = new_item; + } else if (!strcmp(name, "queue")) { + new_item->stype = F_QUEUE; + new_item->folder->queue = new_item; + } else if (!strcmp(name, "trash")) { + new_item->stype = F_TRASH; + new_item->folder->trash = new_item; + } + + g_free(foldername); + g_free(path); + + return new_item; +} + +gint mbox_rename_folder(Folder *folder, FolderItem *item, const gchar *name) +{ + gchar * path; + gchar * foldername; + + 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); + g_return_val_if_fail(name != NULL, -1); + + path = mbox_get_new_path(item->parent, (gchar *) name); + foldername = mbox_get_folderitem_name((gchar *) name); + + if (rename(item->path, path) == -1) { + g_free(foldername); + g_free(path); + g_warning(_("Cannot rename folder item")); + + return -1; + } + else { + g_free(item->name); + g_free(item->path); + item->path = path; + item->name = foldername; + + return 0; + } +} + +gint mbox_remove_folder(Folder *folder, FolderItem *item) +{ + 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); + + folder_item_remove(item); + return 0; +} + diff --git a/src/mbox_folder.h b/src/mbox_folder.h index 38c5027fb..bc513bde9 100644 --- a/src/mbox_folder.h +++ b/src/mbox_folder.h @@ -27,5 +27,15 @@ void mbox_update_mark(Folder * folder, FolderItem * item); gint mbox_move_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist); gint mbox_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo); +void mbox_change_flags(Folder * folder, FolderItem * item, MsgInfo * info); +gint mbox_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo); +gint mbox_copy_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist); +gint mbox_create_tree(Folder *folder); +FolderItem *mbox_create_folder(Folder *folder, FolderItem *parent, + const gchar *name); +gint mbox_rename_folder(Folder *folder, FolderItem *item, const gchar *name); +gint mbox_remove_folder(Folder *folder, FolderItem *item); +void mbox_finished_copy(Folder *folder, FolderItem *dest); + #endif diff --git a/src/mh.c b/src/mh.c index deac16509..5cae5f3ae 100644 --- a/src/mh.c +++ b/src/mh.c @@ -122,6 +122,7 @@ gchar *mh_fetch_msg(Folder *folder, FolderItem *item, gint num) 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; @@ -177,6 +178,7 @@ gint mh_add_msg(Folder *folder, FolderItem *dest, const gchar *file, return dest->last_num; } +/* gint mh_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo) { gchar *destdir; @@ -260,7 +262,32 @@ gint mh_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo) return dest->last_num; } +*/ + +/* +gint mh_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo) +{ + Folder * src_folder; + gchar * filename; + gint num; + gchar * destdir; + + src_folder = msginfo->folder->folder; + + g_return_val_if_fail(src_folder->remove_msg != NULL, -1); + + num = folder->copy_msg(folder, item, msginfo); + + if (num != -1) + src_folder->remove_msg(src_folder, + msginfo->folder, + msginfo->msgnum); + + return num; +} +*/ +/* gint mh_move_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist) { gchar *destdir; @@ -348,7 +375,9 @@ gint mh_move_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist) return dest->last_num; } +*/ +/* gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo) { gchar *destdir; @@ -421,7 +450,52 @@ gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo) return dest->last_num; } +*/ + +gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo) +{ + Folder * src_folder; + gchar * filename; + gint num; + gchar * destdir; + FILE * fp; + + src_folder = msginfo->folder->folder; + + g_return_val_if_fail(src_folder->fetch_msg != NULL, -1); + + filename = src_folder->fetch_msg(src_folder, + msginfo->folder, + msginfo->msgnum); + if (filename == NULL) + return -1; + + num = folder->add_msg(folder, dest, filename, FALSE); + destdir = folder_item_get_path(dest); + if ((fp = procmsg_open_mark_file(destdir, TRUE)) == NULL) + g_warning(_("Can't open mark file.\n")); + + if (fp) { + MsgInfo newmsginfo; + + newmsginfo.msgnum = dest->last_num; + newmsginfo.flags = msginfo->flags; + if (dest->stype == F_OUTBOX || + dest->stype == F_QUEUE || + dest->stype == F_DRAFT || + dest->stype == F_TRASH) + MSG_UNSET_FLAGS(newmsginfo.flags, + MSG_NEW|MSG_UNREAD|MSG_DELETED); + + procmsg_write_flags(&newmsginfo, fp); + fclose(fp); + } + + return num; +} + +/* gint mh_copy_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist) { gchar *destdir; @@ -499,6 +573,7 @@ gint mh_copy_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist) return dest->last_num; } +*/ gint mh_remove_msg(Folder *folder, FolderItem *item, gint num) { diff --git a/src/prefs_filtering.c b/src/prefs_filtering.c index fa2921c51..a4f542c2f 100644 --- a/src/prefs_filtering.c +++ b/src/prefs_filtering.c @@ -370,7 +370,6 @@ static void prefs_filtering_create(void) for (accounts = account_get_list() ; accounts != NULL; accounts = accounts->next) { PrefsAccount *ac = (PrefsAccount *)accounts->data; - GtkWidget *menuitem; gchar *name; name = g_strdup_printf("%s <%s> (%s)", @@ -650,7 +649,7 @@ static FilteringProp * prefs_filtering_dialog_to_filtering(void) cond_str = gtk_entry_get_text(GTK_ENTRY(filtering.cond_entry)); if (*cond_str == '\0') { alertpanel_error(_("Score is not set.")); - return; + return NULL; } action_id = get_sel_from_list(GTK_LIST(filtering.action_list)); @@ -666,7 +665,7 @@ static FilteringProp * prefs_filtering_dialog_to_filtering(void) destination = gtk_entry_get_text(GTK_ENTRY(filtering.dest_entry)); if (*destination == '\0') { alertpanel_error(_("Destination is not set.")); - return; + return NULL; } break; default: @@ -682,7 +681,7 @@ static FilteringProp * prefs_filtering_dialog_to_filtering(void) if (tmp == NULL) { alertpanel_error(_("Match string is not valid.")); filteringaction_free(action); - return; + return NULL; } prop = filteringprop_new(cond, action); diff --git a/src/procheader.c b/src/procheader.c index 561adad52..b4f26d547 100644 --- a/src/procheader.c +++ b/src/procheader.c @@ -56,8 +56,9 @@ gint procheader_get_one_field(gchar *buf, gint len, FILE *fp, for (hp = hentry, hnum = 0; hp->name != NULL; hp++, hnum++) { if (!strncasecmp(hp->name, buf, - strlen(hp->name))) + strlen(hp->name))) { break; + } } } while (hp->name == NULL); } else { @@ -430,8 +431,8 @@ enum H_SEEN = 10, H_STATUS = 11, H_X_STATUS = 12, - H_X_FACE = 13, - H_FROM_SPACE = 14, + H_FROM_SPACE = 13, + H_X_FACE = 14, H_DISPOSITION_NOTIFICATION_TO = 15, H_RETURN_RECEIPT_TO = 16 }; @@ -469,8 +470,8 @@ MsgInfo *procheader_file_parse(FILE * fp, MsgFlags flags, {"Seen:", NULL, FALSE}, {"Status:", NULL, FALSE}, {"X-Status:", NULL, FALSE}, - {"X-Face:", NULL, FALSE}, {"From ", NULL, FALSE}, + {"X-Face:", NULL, FALSE}, {"Disposition-Notification-To:", NULL, FALSE}, {"Return-Receipt-To:", NULL, FALSE}, {NULL, NULL, FALSE}}; @@ -621,8 +622,17 @@ MsgInfo *procheader_file_parse(FILE * fp, MsgFlags flags, MSG_SET_FLAGS(msginfo->flags, MSG_UNREAD); break; case H_X_STATUS: - if (strchr(hp, 'X') != NULL) + if (strchr(hp, 'D') != NULL) + MSG_SET_FLAGS(msginfo->flags, + MSG_REALLY_DELETED); + if (strchr(hp, 'F') != NULL) MSG_SET_FLAGS(msginfo->flags, MSG_MARKED); + if (strchr(hp, 'd') != NULL) + MSG_SET_FLAGS(msginfo->flags, MSG_DELETED); + if (strchr(hp, 'r') != NULL) + MSG_SET_FLAGS(msginfo->flags, MSG_REPLIED); + if (strchr(hp, 'f') != NULL) + MSG_SET_FLAGS(msginfo->flags, MSG_FORWARDED); break; case H_FROM_SPACE: if (msginfo->fromspace) break; diff --git a/src/procmsg.c b/src/procmsg.c index d0d44de80..991adc1ea 100644 --- a/src/procmsg.c +++ b/src/procmsg.c @@ -773,6 +773,7 @@ void procmsg_msginfo_free(MsgInfo *msginfo) { if (msginfo == NULL) return; + g_free(msginfo->fromspace); g_free(msginfo->references); g_free(msginfo->returnreceiptto); g_free(msginfo->dispositionnotificationto); diff --git a/src/procmsg.h b/src/procmsg.h index b7ed1208d..143078662 100644 --- a/src/procmsg.h +++ b/src/procmsg.h @@ -39,6 +39,7 @@ typedef enum MSG_DELETED = 1 << 3, MSG_REPLIED = 1 << 4, MSG_FORWARDED = 1 << 5, + MSG_REALLY_DELETED = 1 << 6, /* temporary flags (0xffff0000) */ MSG_MOVE = 1 << 16, @@ -58,7 +59,8 @@ typedef enum MSG_MARKED | \ MSG_DELETED | \ MSG_REPLIED | \ - MSG_FORWARDED) + MSG_FORWARDED | \ + MSG_REALLY_DELETED) #define MSG_CACHED_FLAG_MASK (MSG_MIME) #define MSG_SET_FLAGS(msg, flags) { (msg) |= (flags); } @@ -72,6 +74,7 @@ typedef enum #define MSG_IS_MOVE(msg) ((msg & MSG_MOVE) != 0) #define MSG_IS_COPY(msg) ((msg & MSG_COPY) != 0) +#define MSG_IS_REALLY_DELETED(msg) ((msg & MSG_REALLY_DELETED) != 0) #define MSG_IS_QUEUED(msg) ((msg & MSG_QUEUED) != 0) #define MSG_IS_DRAFT(msg) ((msg & MSG_DRAFT) != 0) @@ -134,8 +137,6 @@ struct _MsgInfo /* used only for encrypted messages */ gchar *plaintext_file; guint decryption_failed : 1; - - void * data; }; GHashTable *procmsg_msg_hash_table_create (GSList *mlist); diff --git a/src/summaryview.c b/src/summaryview.c index 5b520d815..69d2ecd70 100644 --- a/src/summaryview.c +++ b/src/summaryview.c @@ -1644,6 +1644,14 @@ static void summary_set_header(gchar *text[], MsgInfo *msginfo) _("(No Subject)"); } +#define CHANGE_FLAGS(msginfo) \ +{ \ +if (msginfo->folder->folder->change_flags != NULL) \ +msginfo->folder->folder->change_flags(msginfo->folder->folder, \ + msginfo->folder, \ + msginfo); \ +} + static void summary_display_msg(SummaryView *summaryview, GtkCTreeNode *row, gboolean new_window) { @@ -1697,6 +1705,9 @@ static void summary_display_msg(SummaryView *summaryview, GtkCTreeNode *row, summaryview->unread--; if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) { MSG_UNSET_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD); + + CHANGE_FLAGS(msginfo); + summary_set_row_marks(summaryview, row); gtk_clist_thaw(GTK_CLIST(ctree)); summary_status_show(summaryview); @@ -1888,6 +1899,9 @@ static void summary_mark_row(SummaryView *summaryview, GtkCTreeNode *row) summaryview->copied--; MSG_UNSET_FLAGS(msginfo->flags, MSG_DELETED | MSG_MOVE | MSG_COPY); MSG_SET_FLAGS(msginfo->flags, MSG_MARKED); + + CHANGE_FLAGS(msginfo); + summary_set_row_marks(summaryview, row); debug_print(_("Message %d is marked\n"), msginfo->msgnum); } @@ -1918,6 +1932,9 @@ static void summary_mark_row_as_read(SummaryView *summaryview, if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) { MSG_UNSET_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD); + + CHANGE_FLAGS(msginfo); + summary_set_row_marks(summaryview, row); debug_print(_("Message %d is marked as being read\n"), msginfo->msgnum); @@ -1951,12 +1968,16 @@ static void summary_mark_row_as_unread(SummaryView *summaryview, MSG_UNSET_FLAGS(msginfo->flags, MSG_REPLIED | MSG_FORWARDED); if (!MSG_IS_UNREAD(msginfo->flags)) { MSG_SET_FLAGS(msginfo->flags, MSG_UNREAD); + gtk_ctree_node_set_pixmap(ctree, row, S_COL_UNREAD, unreadxpm, unreadxpmmask); summaryview->unread++; debug_print(_("Message %d is marked as unread\n"), msginfo->msgnum); } + + CHANGE_FLAGS(msginfo); + summary_set_row_marks(summaryview, row); } @@ -1991,6 +2012,9 @@ static void summary_delete_row(SummaryView *summaryview, GtkCTreeNode *row) MSG_MOVE | MSG_COPY); MSG_SET_FLAGS(msginfo->flags, MSG_DELETED); + + CHANGE_FLAGS(msginfo); + summaryview->deleted++; if (!prefs_common.immediate_exec) @@ -2082,6 +2106,9 @@ static void summary_unmark_row(SummaryView *summaryview, GtkCTreeNode *row) MSG_DELETED | MSG_MOVE | MSG_COPY); + + CHANGE_FLAGS(msginfo); + summary_set_row_marks(summaryview, row); debug_print(_("Message %s/%d is unmarked\n"), @@ -2118,6 +2145,7 @@ static void summary_move_row_to(SummaryView *summaryview, GtkCTreeNode *row, MSG_SET_FLAGS(msginfo->flags, MSG_MOVE); summaryview->moved++; } + if (!prefs_common.immediate_exec) summary_set_row_marks(summaryview, row); @@ -2179,6 +2207,7 @@ static void summary_copy_row_to(SummaryView *summaryview, GtkCTreeNode *row, MSG_SET_FLAGS(msginfo->flags, MSG_COPY); summaryview->copied++; } + if (!prefs_common.immediate_exec) summary_set_row_marks(summaryview, row); @@ -2314,7 +2343,8 @@ void summary_execute(SummaryView *summaryview) gtk_clist_freeze(clist); - if (prefs_common.enable_thread) + if (summaryview->folder_item->prefs->enable_thread) + /* if (prefs_common.enable_thread) */ summary_unthread_for_exec(summaryview); summary_execute_move(summaryview); @@ -2337,7 +2367,8 @@ void summary_execute(SummaryView *summaryview) node = next; } - if (prefs_common.enable_thread) + if (summaryview->folder_item->prefs->enable_thread) + /* if (prefs_common.enable_thread) */ summary_thread_build(summaryview); summaryview->selected = clist->selection ? @@ -2451,6 +2482,7 @@ static void summary_execute_copy_func(GtkCTree *ctree, GtkCTreeNode *node, g_slist_append(summaryview->mlist, msginfo); MSG_UNSET_FLAGS(msginfo->flags, MSG_COPY); + summary_set_row_marks(summaryview, node); } } @@ -2927,6 +2959,9 @@ static void summary_selected(GtkCTree *ctree, GtkCTreeNode *row, case S_COL_MARK: if (MSG_IS_MARKED(msginfo->flags)) { MSG_UNSET_FLAGS(msginfo->flags, MSG_MARKED); + + CHANGE_FLAGS(msginfo); + summary_set_row_marks(summaryview, row); } else summary_mark_row(summaryview, row); diff --git a/src/textview.c b/src/textview.c index fa44ba929..80b250805 100644 --- a/src/textview.c +++ b/src/textview.c @@ -974,7 +974,7 @@ static GPtrArray *textview_scan_header(TextView *textview, FILE *fp) } } - g_ptr_array_free(headers, TRUE); + g_ptr_array_free(headers, FALSE); return sorted_headers; } @@ -995,7 +995,9 @@ static void textview_show_header(TextView *textview, GPtrArray *headers) gtk_text_insert(text, textview->boldfont, NULL, NULL, header->name, -1); - gtk_text_insert(text, textview->boldfont, NULL, NULL, " ", 1); + if (header->name[strlen(header->name) - 1] != ' ') + gtk_text_insert(text, textview->boldfont, + NULL, NULL, " ", 1); if (procheader_headername_equal(header->name, "Subject") || procheader_headername_equal(header->name, "From") || -- 2.25.1