[sylpheed:35200] Re: [PATCH] Maildir import and export support

Steve Brokenshire sbrokenshire at xestia.co.uk
Thu Apr 12 01:44:55 JST 2012


Hello again,

(Apologies for the mess up in your emails and mailing list archive -
thought Digest would be easier for me but turns that it really isn't
the case for me).

Please find attached an updated patch for Maildir import and export.
This version replaces the fixed-length buffers and strcpy/strcat with
pointers and g_strconcat().

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-04-09 10:34:35.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,122 @@
 	return ok;
 }
 
+static gint import_maildir(FolderItem *dest, const gchar *path)
+{
+	gchar *path_new;
+	gchar *path_cur;
+	gchar *path_tmp;
+	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) */
+	
+	path_new = g_strconcat(path, "/new/", NULL);
+	
+	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) */
+
+	path_cur = g_strconcat(path, "/cur/", NULL);	
+	
+	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) */
+	
+	path_tmp = g_strconcat(path, "/tmp/", NULL);
+	
+	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 +769,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 +846,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-09 18:05:19.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,159 @@
 	return ok;
 }
 
+static gint export_maildir(FolderItem *src, const gchar *path, gint type)
+{
+ 
+	gchar *path_new;
+	gchar *path_cur;
+	gchar *path_tmp;
+	gint ok = 0;
+	GSList *mlist, *cur;
+	MsgInfo *msginfo;
+	gchar *file, *dest;
+	gint count = 0;
+	
+	/* Export the unread messages in the new directory */
+	
+	path_new = g_strconcat(path, "/new/", NULL);	
+	
+	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 */
+
+	path_cur = g_strconcat(path, "/cur/", NULL);		
+
+	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. */
+
+	path_tmp = g_strconcat(path, "/tmp/", NULL);
+  
+	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 +527,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