[sylpheed:35197] [PATCH] Maildir import and export support

Steve Brokenshire sbrokenshire at xestia.co.uk
Thu Apr 5 04:41:17 JST 2012


Hello,

Please find below a patch to enable Sylpheed to import from and export to Maildir directories. Most of it was based off existing code in import.c/export.c for dealing with folders which contained EML files. :)

When importing, it treats messages in the new and tmp directories as unread and messages in the cur directory as read. When exporting, it places unread messages in the new directory and read messages in the cur directory.

To prevent data being overwritten on exporting, directory creation is attempted on each of the cur, new and tmp directories and stops if it can't create the directory as it already exists or something else has happened.

Regards,
Steve Brokenshire

Patch follows...

--- sylpheed-3.1.3-orig/src/import.c	2011-09-07 05:23:20.000000000 +0100
+++ sylpheed-3.1.3/src/import.c	2012-03-28 18:25:56.000000000 +0100
@@ -69,7 +69,8 @@
 {
 	IMPORT_MBOX,
 	IMPORT_EML_FOLDER,
-	IMPORT_DBX
+	IMPORT_DBX,
+	IMPORT_MAILDIR
 };
 
 static GtkWidget *window;
@@ -94,6 +95,9 @@
 static gint import_dbx		(FolderItem	*dest,
 				 const gchar	*file);
 
+static gint import_maildir	(FolderItem	*dest,
+				 const gchar	*path);
+
 static void import_format_menu_cb	(GtkWidget	*widget,
 					 gpointer	 data);
 
@@ -243,6 +247,8 @@
 		ok = import_eml_folder(dest, filename);
 	} else if (type == IMPORT_DBX) {
 		ok = import_dbx(dest, filename);
+	} else if (type == IMPORT_MAILDIR) {
+		ok = import_maildir(dest, filename);
 	}
 
 	progress_dialog_set_label(progress, _("Scanning folder..."));
@@ -577,6 +583,125 @@
 	return ok;
 }
 
+static gint import_maildir(FolderItem *dest, const gchar *path)
+{
+	gchar path_new[4096];
+	gchar path_cur[4096];
+	gchar path_tmp[4096];
+	GDir *dir;
+	const gchar *dir_name, *p;
+	gchar *file;
+	const gchar *filename;
+	MsgInfo *msginfo;
+	MsgFlags flags = {MSG_NEW|MSG_UNREAD, MSG_RECEIVED};
+	gint count = 0;
+	gint ok = 0;
+	
+	g_return_val_if_fail(dest != NULL, -1);
+	g_return_val_if_fail(path != NULL, -1);	
+	
+	debug_print("path: %s\n", path);
+	
+	/* Process the files in the new folder (mark them as new) */
+	
+	strcpy(path_new, path);
+	strcat(path_new, "/new/");
+	
+	debug_print("path_new: %s\n", path_new);
+	
+	if (import_maildir_processdir(dest, path_new, 0) < 0){
+		debug_print("import_maildir_processdir: error occured whilst processing %s\n", path_new);
+		ok = -1;
+		return ok;
+	}
+
+	/* Process the files in the cur folder (mark them as read) */
+
+	strcpy(path_cur, path);
+	strcat(path_cur, "/cur/");	
+	
+	debug_print("path_cur: %s\n", path_cur);
+	
+	if (import_maildir_processdir(dest, path_cur, 1) < 0){
+	  	debug_print("import_maildir_processdir: error occured whilst processing %s\n", path_cur);
+		ok = -1;
+		return ok;
+	}	
+	
+	/* Process the files in the tmp folder (mark them as new) */
+	
+	strcpy(path_tmp, path);
+	strcat(path_tmp, "/tmp/");
+	
+	debug_print("path_tmp: %s\n", path_tmp);
+	
+	if (import_maildir_processdir(dest, path_tmp, 0) < 0){
+		debug_print("import_maildir_processdir: error occured whilst processing %s\n", path_tmp);	  
+		ok = -1;
+		return ok;
+	}
+	
+	return ok;
+	
+}
+
+gint import_maildir_processdir(FolderItem *dest, gchar *path, gint markread)
+{
+	GDir *dir;
+	gchar *file;
+	const gchar *filename;
+	MsgInfo *msginfo;
+	MsgFlags flags = {MSG_NEW|MSG_UNREAD, MSG_RECEIVED};
+	gint count = 0;
+	gint ok = 0;
+  
+	debug_print("import_maildir_processdir path: %s\n", path);
+	
+	if ((dir = g_dir_open(path, 0, NULL)) == NULL) {
+		g_warning("failed to open maildir directory: %s", path);
+		return -1;
+	}
+
+	while((filename = g_dir_read_name(dir)) != NULL){
+	  
+
+		file = g_strconcat(path, G_DIR_SEPARATOR_S, filename, NULL);
+
+		debug_print("Reading file %s\n", file);
+		
+		if (!g_file_test(file, G_FILE_TEST_IS_REGULAR)) {
+			g_free(file);
+			continue;
+		}
+		msginfo = procheader_parse_file(file, flags, FALSE);
+		if (!msginfo) {
+			g_warning("import_maildir_processdir(): procheader_parse_file() failed.\n");
+			g_free(file);
+			continue;
+		}		
+		msginfo->file_path = file;
+		if (markread == 1)
+			MSG_UNSET_PERM_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD);
+		file = NULL;
+		count++;
+		proc_mbox_func(dest->folder, dest,
+			       GINT_TO_POINTER(count));
+		ok = folder_item_add_msg_msginfo(dest, msginfo, FALSE);
+		if (ok < 0) {
+			g_warning("import_maildir_processdir(): folder_item_add_msg_msginfo() failed.\n", count);
+			break;
+		}		
+		procmsg_msginfo_free(msginfo);
+		if (import_progress_cancelled)
+		break;
+	}
+
+	g_dir_close(dir);
+	
+	return ok;
+  
+}
+
 static void import_create(void)
 {
 	GtkWidget *vbox;
@@ -647,6 +772,9 @@
 	MENUITEM_ADD(menu, menuitem, _("Outlook Express (dbx)"), IMPORT_DBX);
 	g_signal_connect(G_OBJECT(menuitem), "activate",
 			 G_CALLBACK(import_format_menu_cb), NULL);
+	MENUITEM_ADD(menu, menuitem, _("Maildir (folder)"), IMPORT_MAILDIR);
+	g_signal_connect(G_OBJECT(menuitem), "activate",
+			 G_CALLBACK(import_format_menu_cb), NULL);
 
 	gtk_option_menu_set_menu(GTK_OPTION_MENU(format_optmenu), menu);
 
@@ -721,7 +849,7 @@
 	type = menu_get_option_menu_active_index
 		(GTK_OPTION_MENU(format_optmenu));
 
-	if (type == IMPORT_EML_FOLDER)
+	if (type == IMPORT_EML_FOLDER || type == IMPORT_MAILDIR)
 		filename = filesel_select_file
 			(_("Select importing folder"), NULL,
 			 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
--- sylpheed-3.1.3-orig/src/export.c	2011-09-07 05:23:20.000000000 +0100
+++ sylpheed-3.1.3/src/export.c	2012-04-04 10:22:37.000000000 +0100
@@ -59,7 +59,8 @@
 {
 	EXPORT_MBOX,
 	EXPORT_EML,
-	EXPORT_MH
+	EXPORT_MH,
+	EXPORT_MAILDIR
 };
 
 static GtkWidget *window;
@@ -82,6 +83,10 @@
 				 const gchar	*path,
 				 gint		 type);
 
+static gint export_maildir	(FolderItem	*src,
+				 const gchar	*path,
+				 gint		 type);
+
 static void export_format_menu_cb	(GtkWidget	*widget,
 					 gpointer	 data);
 
@@ -218,6 +223,8 @@
 		folder_set_ui_func(src->folder, NULL, NULL);
 	} else if (type == EXPORT_EML || type == EXPORT_MH) {
 		ok = export_eml(src, mbox, type);
+	} else if (type == EXPORT_MAILDIR){
+		ok = export_maildir(src, mbox, type);
 	}
 
 	progress_dialog_destroy(progress);
@@ -297,6 +304,162 @@
 	return ok;
 }
 
+static gint export_maildir(FolderItem *src, const gchar *path, gint type)
+{
+ 
+	gchar path_new[4096];
+	gchar path_cur[4096];
+	gchar path_tmp[4096];
+	gint ok = 0;
+	GSList *mlist, *cur;
+	MsgInfo *msginfo;
+	gchar *file, *dest;
+	gint count = 0;
+	
+	/* Export the unread messages in the new directory */
+	
+	strcpy(path_new, path);
+	strcat(path_new, "/new/");
+	
+	debug_print("path_new: %s\n", path_new);	
+
+	if (!g_file_test(path_new, G_FILE_TEST_IS_DIR)) {
+		if (!g_file_test(path_new, G_FILE_TEST_EXISTS)) {
+			make_dir_hier(path_new);
+			if (!g_file_test(path_new, G_FILE_TEST_IS_DIR)){
+			  	g_warning("export_maildir(): Cannot create new directory %s.",
+				  path_new);
+				return -1;
+			}
+		} else {
+			g_warning("export_maildir(): Directory %s already exists.",
+				  path_new);
+			return -1;
+		}
+	}
+
+	debug_print("path_new (directory name): %s\n", path_new);	
+
+	if (export_maildir_process(src, path_new, 0) != 0){
+		ok = -1;
+		return ok;
+	}	
+	
+	/* Export the read messages in the cur directory */
+
+	strcpy(path_cur, path);
+	strcat(path_cur, "/cur/");		
+
+	debug_print("path_cur: %s\n", path_cur);	
+
+	if (!g_file_test(path_cur, G_FILE_TEST_IS_DIR)) {
+		if (!g_file_test(path_cur, G_FILE_TEST_EXISTS)) {
+			make_dir_hier(path_cur);
+			if (!g_file_test(path_cur, G_FILE_TEST_IS_DIR)){
+			  	g_warning("export_maildir(): Cannot create cur directory %s.",
+				  path_cur);
+				return -1;
+			}
+		} else {
+			g_warning("export_maildir(): Directory %s already exists.",
+				  path_cur);
+			return -1;
+		}
+	}
+	
+	debug_print("path_cur (directory name): %s\n", path_cur);	
+
+	if (export_maildir_process(src, path_cur, 1) != 0){
+		return -1;
+	}	
+	
+	/* Create empty tmp folder for completeness. */
+
+	strcpy(path_tmp, path);
+	strcat(path_tmp, "/tmp/");	
+  
+	debug_print("path_tmp: %s\n", path_tmp);	
+	
+	if (!g_file_test(path_tmp, G_FILE_TEST_IS_DIR)) {
+		if (!g_file_test(path_tmp, G_FILE_TEST_EXISTS)) {
+			make_dir_hier(path_tmp);
+			if (!g_file_test(path_tmp, G_FILE_TEST_IS_DIR)){
+			  	g_warning("export_maildir(): Cannot create tmp directory %s.",
+				  path_tmp);
+				return -1;
+			}
+		} else {
+			g_warning("export_maildir(): Directory %s already exists.",
+				  path_tmp);
+			return -1;
+		}
+	}	
+	
+	debug_print("path_tmp (directory name): %s\n", path_tmp);	
+	
+	return ok;
+  
+}
+
+gint export_maildir_process(FolderItem *src, const gchar *path, gint msgreadfilter){
+ 
+	gint ok = 0;
+	GSList *mlist, *cur;
+	MsgInfo *msginfo;
+	gchar *file, *dest;
+	gint count = 0;	
+
+	mlist = folder_item_get_msg_list(src, TRUE);
+	if (!mlist)
+		return 0;		
+	for (cur = mlist; cur != NULL; cur = cur->next) {
+		msginfo = (MsgInfo *)cur->data;
+		
+		if (msgreadfilter == 1){
+		
+			if (MSG_IS_UNREAD(msginfo->flags))
+				continue;
+		
+		} else {
+
+			if (!MSG_IS_UNREAD(msginfo->flags))
+				continue;		  
+		  
+		}
+		
+		count++;
+		export_mbox_func(src->folder, src, GINT_TO_POINTER(count));
+
+		file = folder_item_fetch_msg(src, msginfo->msgnum);
+		if (!file) {
+			ok = -1;
+			break;
+		}
+		dest = g_strdup_printf("%s%c%d", path, G_DIR_SEPARATOR,
+				       count);
+		if (g_file_test(dest, G_FILE_TEST_EXISTS)) {
+			g_warning("export_maildir(): %s already exists.", dest);
+			g_free(dest);
+			g_free(file);
+			ok = -1;
+			break;
+		}
+		if (copy_file(file, dest, FALSE) < 0) {
+			g_free(dest);
+			g_free(file);
+			ok = -1;
+			break;
+		}
+		g_free(dest);
+		g_free(file);
+	}
+
+	procmsg_msg_list_free(mlist);
+	
+	return ok;
+	
+};
+
 static void export_create(void)
 {
 	GtkWidget *vbox;
@@ -367,6 +530,9 @@
 	MENUITEM_ADD(menu, menuitem, _("MH (number only)"), EXPORT_MH);
 	g_signal_connect(G_OBJECT(menuitem), "activate",
 			 G_CALLBACK(export_format_menu_cb), NULL);
+	MENUITEM_ADD(menu, menuitem, _("Maildir (folder)"), EXPORT_MAILDIR);
+	g_signal_connect(G_OBJECT(menuitem), "activate",
+			 G_CALLBACK(export_format_menu_cb), NULL);
 
 	gtk_option_menu_set_menu(GTK_OPTION_MENU(format_optmenu), menu);
 


More information about the Sylpheed mailing list