aboutsummaryrefslogtreecommitdiffstats
path: root/mail/mail-local.c
diff options
context:
space:
mode:
authorDan Winship <danw@src.gnome.org>2001-02-10 00:45:09 +0800
committerDan Winship <danw@src.gnome.org>2001-02-10 00:45:09 +0800
commitfa2c19fdd1aee26d8bf5b622a3adf970004c3abf (patch)
treeffd18597510f602e430c08224748ab44761888ba /mail/mail-local.c
parentec981301f5489626ffbf9474db49f1fda4e41a99 (diff)
downloadgsoc2013-evolution-fa2c19fdd1aee26d8bf5b622a3adf970004c3abf.tar.gz
gsoc2013-evolution-fa2c19fdd1aee26d8bf5b622a3adf970004c3abf.tar.zst
gsoc2013-evolution-fa2c19fdd1aee26d8bf5b622a3adf970004c3abf.zip
Updates for CamelStore changes, small memory leak fixes. (lookup_folder):
* mail-local.c: Updates for CamelStore changes, small memory leak fixes. (lookup_folder): Removed (and moved into the reconfigure code) since this method no longer exists in CamelStore. (do_reconfigure_folder, etc): Update the info in the MailLocalStore after reconfiguring. (mail_local_lookup_folder): Removed * local-config.glade: fix padding of the label_format * message-list.c (ml_tree_value_at): Don't keep message infos reffed across calls, since this can cause badness after a reconfigure. Instead, just strdup the needed values and free those on the next call. * mail-tools.c (mail_tool_get_root_of_store): Unused, remove. (mail_tool_get_inbox): use camel_store_get_inbox. * evolution-outlook-importer.c (load_file_fn): * evolution-mbox-importer.c (load_file_fn): Use mail_tool_get_local_inbox() instead of mail_importer_get_folder() * mail-importer.c (mail_importer_get_folder): Removed svn path=/trunk/; revision=8147
Diffstat (limited to 'mail/mail-local.c')
-rw-r--r--mail/mail-local.c774
1 files changed, 340 insertions, 434 deletions
diff --git a/mail/mail-local.c b/mail/mail-local.c
index 1559418a83..7b5b744018 100644
--- a/mail/mail-local.c
+++ b/mail/mail-local.c
@@ -162,315 +162,6 @@ save_metainfo(struct _local_meta *meta)
}
-/* Local folder reconfiguration stuff */
-
-/*
- open new
- copy old->new
- close old
- rename old oldsave
- rename new old
- open oldsave
- delete oldsave
-
- close old
- rename oldtmp
- open new
- open oldtmp
- copy oldtmp new
- close oldtmp
- close oldnew
-
-*/
-
-static void
-update_progress(char *fmt, float percent)
-{
- if (fmt)
- mail_status(fmt);
- /*mail_op_set_percentage (percent);*/
-}
-
-/* ******************** */
-
-typedef struct reconfigure_folder_input_s {
- FolderBrowser *fb;
- gchar *newtype;
- GtkWidget *frame;
- GtkWidget *apply;
- GtkWidget *cancel;
- GtkOptionMenu *optionlist;
-} reconfigure_folder_input_t;
-
-static gchar *
-describe_reconfigure_folder (gpointer in_data, gboolean gerund)
-{
- reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data;
-
- if (gerund)
- return g_strdup_printf (_("Changing folder \"%s\" to \"%s\" format"),
- input->fb->uri,
- input->newtype);
- else
- return g_strdup_printf (_("Change folder \"%s\" to \"%s\" format"),
- input->fb->uri,
- input->newtype);
-}
-
-static void
-setup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex)
-{
- reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data;
-
- if (!IS_FOLDER_BROWSER (input->fb)) {
- camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
- "Input has a bad FolderBrowser in reconfigure_folder");
- return;
- }
-
- if (!input->newtype) {
- camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
- "No new folder type in reconfigure_folder");
- return;
- }
-
- gtk_object_ref (GTK_OBJECT (input->fb));
-}
-
-static void
-do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex)
-{
- reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data;
-
- CamelStore *fromstore = NULL, *tostore = NULL;
- char *fromurl = NULL, *tourl = NULL;
- CamelFolder *fromfolder = NULL, *tofolder = NULL;
- GPtrArray *uids;
- int i;
- char *metapath;
- char *tmpname;
- CamelURL *url = NULL;
- struct _local_meta *meta;
- guint32 flags;
-
- d(printf("reconfiguring folder: %s to type %s\n", input->fb->uri, input->newtype));
-
- mail_status_start(_("Reconfiguring folder"));
-
- /* NOTE: This var is cleared by the folder_browser via the set_uri method */
- input->fb->reconfigure = TRUE;
-
- /* get the actual location of the mailbox */
- url = camel_url_new(input->fb->uri, ex);
- if (camel_exception_is_set(ex)) {
- g_warning("%s is not a workable url!", input->fb->uri);
- goto cleanup;
- }
-
- metapath = g_strdup_printf("%s/local-metadata.xml", url->path);
- meta = load_metainfo(metapath);
- g_free(metapath);
-
- /* first, 'close' the old folder */
- if (input->fb->folder != NULL) {
- update_progress(_("Closing current folder"), 0.0);
-
- camel_folder_sync(input->fb->folder, FALSE, ex);
- camel_object_unref (CAMEL_OBJECT (input->fb->folder));
- input->fb->folder = NULL;
- }
-
- camel_url_set_protocol (url, meta->format);
- fromurl = camel_url_to_string (url, FALSE);
- camel_url_set_protocol (url, input->newtype);
- tourl = camel_url_to_string (url, FALSE);
-
- d(printf("opening stores %s and %s\n", fromurl, tourl));
-
- fromstore = camel_session_get_store(session, fromurl, ex);
-
- if (camel_exception_is_set(ex))
- goto cleanup;
-
- tostore = camel_session_get_store(session, tourl, ex);
- if (camel_exception_is_set(ex))
- goto cleanup;
-
- /* rename the old mbox and open it again, without indexing */
- tmpname = g_strdup_printf("%s_reconfig", meta->name);
- d(printf("renaming %s to %s, and opening it\n", meta->name, tmpname));
- update_progress(_("Renaming old folder and opening"), 0.0);
-
- camel_store_rename_folder(fromstore, meta->name, tmpname, ex);
- if (camel_exception_is_set(ex)) {
- goto cleanup;
- }
-
- /* we dont need to set the create flag ... or need an index if it has one */
- fromfolder = camel_store_get_folder(fromstore, tmpname, 0, ex);
- if (fromfolder == NULL || camel_exception_is_set(ex)) {
- /* try and recover ... */
- camel_exception_clear (ex);
- camel_store_rename_folder(fromstore, tmpname, meta->name, ex);
- goto cleanup;
- }
-
- /* create a new mbox */
- d(printf("Creating the destination mbox\n"));
- update_progress(_("Creating new folder"), 0.0);
-
- flags = CAMEL_STORE_FOLDER_CREATE;
- if (meta->indexed)
- flags |= CAMEL_STORE_FOLDER_BODY_INDEX;
- tofolder = camel_store_get_folder(tostore, meta->name, flags, ex);
- if (tofolder == NULL || camel_exception_is_set(ex)) {
- d(printf("cannot open destination folder\n"));
- /* try and recover ... */
- camel_exception_clear (ex);
- camel_store_rename_folder(fromstore, tmpname, meta->name, ex);
- goto cleanup;
- }
-
- update_progress(_("Copying messages"), 0.0);
- uids = camel_folder_get_uids(fromfolder);
- for (i=0;i<uids->len;i++) {
- mail_statusf("Copying message %d of %d", i, uids->len);
- camel_folder_move_message_to(fromfolder, uids->pdata[i], tofolder, ex);
- if (camel_exception_is_set(ex)) {
- camel_folder_free_uids(fromfolder, uids);
- goto cleanup;
- }
- }
- camel_folder_free_uids(fromfolder, uids);
- camel_folder_expunge(fromfolder, ex);
-
- d(printf("delete old mbox ...\n"));
- camel_store_delete_folder(fromstore, tmpname, ex);
-
- /* switch format */
- g_free(meta->format);
- meta->format = g_strdup(input->newtype);
- if (save_metainfo(meta) == -1) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Cannot save folder metainfo; "
- "you'll probably find you can't\n"
- "open this folder anymore: %s"),
- tourl);
- }
- free_metainfo(meta);
-
- /* and unref our copy of the new folder ... */
- cleanup:
- if (tofolder)
- camel_object_unref (CAMEL_OBJECT (tofolder));
- if (fromfolder)
- camel_object_unref (CAMEL_OBJECT (fromfolder));
- if (fromstore)
- camel_object_unref (CAMEL_OBJECT (fromstore));
- if (tostore)
- camel_object_unref (CAMEL_OBJECT (tostore));
- g_free(fromurl);
- g_free(tourl);
- if (url)
- camel_url_free (url);
-}
-
-static void
-cleanup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex)
-{
- reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data;
- char *uri;
-
- if (camel_exception_is_set(ex)) {
- GtkWidget *win = gtk_widget_get_ancestor((GtkWidget *)input->frame, GTK_TYPE_WINDOW);
- gnome_error_dialog_parented (_("If you can no longer open this mailbox, then\n"
- "you may need to repair it manually."), GTK_WINDOW (win));
- }
-
- /* force a reload of the newly formatted folder */
- d(printf("opening new source\n"));
- uri = g_strdup(input->fb->uri);
- folder_browser_set_uri(input->fb, uri);
- g_free(uri);
-
- mail_status_end();
-
- gtk_object_unref (GTK_OBJECT (input->fb));
- g_free (input->newtype);
-}
-
-static const mail_operation_spec op_reconfigure_folder =
-{
- describe_reconfigure_folder,
- 0,
- setup_reconfigure_folder,
- do_reconfigure_folder,
- cleanup_reconfigure_folder
-};
-
-static void
-reconfigure_clicked(GnomeDialog *d, int button, reconfigure_folder_input_t *data)
-{
- if (button == 0) {
- GtkMenu *menu;
- int type;
- char *types[] = { "mbox", "maildir", "mh" };
-
- menu = (GtkMenu *)gtk_option_menu_get_menu(data->optionlist);
- type = g_list_index(GTK_MENU_SHELL(menu)->children, gtk_menu_get_active(menu));
- if (type < 0 || type > 2)
- type = 0;
-
- gtk_widget_set_sensitive(data->frame, FALSE);
- gtk_widget_set_sensitive(data->apply, FALSE);
- gtk_widget_set_sensitive(data->cancel, FALSE);
-
- data->newtype = g_strdup (types[type]);
- mail_operation_queue (&op_reconfigure_folder, data, TRUE);
- }
-
- if (button != -1)
- gnome_dialog_close(d);
-}
-
-void
-mail_local_reconfigure_folder(FolderBrowser *fb)
-{
- CamelStore *store;
- GladeXML *gui;
- GnomeDialog *gd;
- reconfigure_folder_input_t *data;
-
- if (fb->folder == NULL) {
- g_warning("Trying to reconfigure nonexistant folder");
- return;
- }
-
- data = g_new (reconfigure_folder_input_t, 1);
-
- store = camel_folder_get_parent_store(fb->folder);
-
- gui = glade_xml_new(EVOLUTION_GLADEDIR "/local-config.glade", "dialog_format");
- gd = (GnomeDialog *)glade_xml_get_widget (gui, "dialog_format");
-
- data->frame = glade_xml_get_widget (gui, "frame_format");
- data->apply = glade_xml_get_widget (gui, "apply_format");
- data->cancel = glade_xml_get_widget (gui, "cancel_format");
- data->optionlist = (GtkOptionMenu *)glade_xml_get_widget (gui, "option_format");
- data->newtype = NULL;
- data->fb = fb;
-
- gtk_label_set_text((GtkLabel *)glade_xml_get_widget (gui, "label_format"),
- ((CamelService *)store)->url->protocol);
-
- gtk_signal_connect((GtkObject *)gd, "clicked", reconfigure_clicked, data);
- gtk_object_unref((GtkObject *)gui);
-
- gnome_dialog_run_and_close (GNOME_DIALOG (gd));
-}
-
-
-
/* MailLocalStore implementation */
#define MAIL_LOCAL_STORE_TYPE (mail_local_store_get_type ())
#define MAIL_LOCAL_STORE(obj) (CAMEL_CHECK_CAST((obj), MAIL_LOCAL_STORE_TYPE, MailLocalStore))
@@ -496,20 +187,20 @@ typedef struct {
typedef struct {
CamelFolder *folder;
MailLocalStore *local_store;
- char *path, *name;
+ char *path, *name, *uri;
int last_unread;
} MailLocalFolder;
-static void local_folder_changed_proxy (CamelObject *folder, gpointer event_data, gpointer user_data);
+static MailLocalStore *local_store;
CamelType mail_local_store_get_type (void);
+static void local_folder_changed_proxy (CamelObject *folder, gpointer event_data, gpointer user_data);
+
static char *get_name(CamelService *service, gboolean brief);
static CamelFolder *get_folder(CamelStore *store, const char *folder_name, guint32 flags, CamelException *ex);
static void delete_folder(CamelStore *store, const char *folder_name, CamelException *ex);
static void rename_folder(CamelStore *store, const char *old_name, const char *new_name, CamelException *ex);
-static char *get_folder_name(CamelStore *store, const char *folder_name, CamelException *ex);
-static CamelFolder *lookup_folder(CamelStore *store, const char *folder_name);
static CamelStoreClass *local_parent_class;
@@ -524,11 +215,13 @@ mail_local_store_class_init (MailLocalStoreClass *mail_local_store_class)
/* virtual method overload */
camel_service_class->get_name = get_name;
+ /* Don't cache folders */
+ camel_store_class->hash_folder_name = NULL;
+ camel_store_class->compare_folder_name = NULL;
+
camel_store_class->get_folder = get_folder;
camel_store_class->delete_folder = delete_folder;
camel_store_class->rename_folder = rename_folder;
- camel_store_class->get_folder_name = get_folder_name;
- camel_store_class->lookup_folder = lookup_folder;
local_parent_class = (CamelStoreClass *)camel_type_get_global_classfuncs(camel_store_get_type ());
}
@@ -555,6 +248,7 @@ free_local_folder(MailLocalFolder *lf)
}
g_free(lf->path);
g_free(lf->name);
+ g_free(lf->uri);
camel_object_unref((CamelObject *)lf->local_store);
}
@@ -608,88 +302,6 @@ mail_local_store_get_type (void)
return mail_local_store_type;
}
-/* sigh,
- because of all this LocalStore nonsense, we have to snoop cache hits to find out
- if our local folder type has changed under us (sort of the whole point of most
- of this file, is the storage type of the folder), and then reload the new folder
- to match.
-
- The only other way would be to poke it even more directly, which seems worse.
-
- Not sure if the ref stuff is 100%, but its probably no worse than it was.
-*/
-static CamelFolder *
-lookup_folder (CamelStore *store, const char *folder_name)
-{
- char *name, *type;
- struct _local_meta *meta;
- MailLocalFolder *local_folder;
- CamelStore *newstore;
- MailLocalStore *local_store = (MailLocalStore *)store;
- CamelFolder *folder;
- CamelException *ex;
-
- folder = local_parent_class->lookup_folder(store, folder_name);
-
- d(printf("looking up local folder: %s = %p\n", folder_name, folder));
-
- if (folder != NULL) {
- type = ((CamelService *)folder->parent_store)->url->protocol;
- name = g_strdup_printf("/%s/local-metadata.xml", folder_name);
- meta = load_metainfo(name);
- g_free(name);
- d(printf("found folder, checking type '%s' against meta '%s'\n", type, meta->format));
- if (strcmp(meta->format, type) != 0) {
- d(printf("ok, mismatch, checking ...\n"));
- local_parent_class->uncache_folder(store, folder);
- local_folder = g_hash_table_lookup(local_store->folders, folder_name);
- if (local_folder) {
- d(printf("we have to update the old folder ...\n"));
- camel_object_unhook_event(CAMEL_OBJECT (local_folder->folder),
- "folder_changed", local_folder_changed_proxy,
- local_folder);
- camel_object_unhook_event(CAMEL_OBJECT (local_folder->folder),
- "message_changed", local_folder_changed_proxy,
- local_folder);
- camel_object_unref((CamelObject *)local_folder->folder);
- folder = local_folder->folder = NULL;
-
- ex = camel_exception_new();
- name = g_strdup_printf ("%s:/%s", meta->format, folder_name);
- newstore = camel_session_get_store (session, name, ex);
- d(printf("getting new store %s = %p\n", name, newstore));
- g_free (name);
- if (newstore) {
- guint32 flags = CAMEL_STORE_FOLDER_CREATE;
- if (meta->indexed)
- flags |= CAMEL_STORE_FOLDER_BODY_INDEX;
- folder = local_folder->folder =
- camel_store_get_folder(newstore, meta->name, flags, ex);
- camel_object_unref((CamelObject *)newstore);
-
- d(printf("we got the new folder: %s : %p\n", folder_name, folder));
- camel_object_hook_event (CAMEL_OBJECT (local_folder->folder),
- "folder_changed", local_folder_changed_proxy,
- local_folder);
- camel_object_hook_event (CAMEL_OBJECT (local_folder->folder),
- "message_changed", local_folder_changed_proxy,
- local_folder);
- }
- if (folder)
- local_parent_class->cache_folder(store, folder_name, folder);
-
- camel_exception_free(ex);
- }
- }
- free_metainfo(meta);
- }
-
- if (folder)
- camel_object_ref((CamelObject *)folder);
-
- return folder;
-}
-
static CamelFolder *
get_folder (CamelStore *store, const char *folder_name,
guint32 flags, CamelException *ex)
@@ -723,13 +335,6 @@ rename_folder (CamelStore *store, const char *old, const char *new,
}
static char *
-get_folder_name (CamelStore *store, const char *folder_name,
- CamelException *ex)
-{
- return g_strdup (folder_name);
-}
-
-static char *
get_name (CamelService *service, gboolean brief)
{
return g_strdup ("Local mail folders");
@@ -800,16 +405,16 @@ static void
do_register_folder (gpointer in_data, gpointer op_data, CamelException *ex)
{
MailLocalFolder *local_folder = in_data;
- char *name;
+ char *name, *path = local_folder->uri + 7;
struct _local_meta *meta;
CamelStore *store;
guint32 flags;
- name = g_strdup_printf ("/%s/local-metadata.xml", local_folder->name);
+ name = g_strdup_printf ("%s/local-metadata.xml", path);
meta = load_metainfo (name);
g_free (name);
- name = g_strdup_printf ("%s:/%s", meta->format, local_folder->name);
+ name = g_strdup_printf ("%s:%s", meta->format, path);
store = camel_session_get_store (session, name, ex);
g_free (name);
if (!store) {
@@ -821,7 +426,16 @@ do_register_folder (gpointer in_data, gpointer op_data, CamelException *ex)
if (meta->indexed)
flags |= CAMEL_STORE_FOLDER_BODY_INDEX;
local_folder->folder = camel_store_get_folder (store, meta->name, flags, ex);
- local_folder->last_unread = camel_folder_get_unread_message_count(local_folder->folder);
+ if (local_folder->folder) {
+ camel_object_hook_event (CAMEL_OBJECT (local_folder->folder),
+ "folder_changed", local_folder_changed_proxy,
+ local_folder);
+ camel_object_hook_event (CAMEL_OBJECT (local_folder->folder),
+ "message_changed", local_folder_changed_proxy,
+ local_folder);
+ local_folder->last_unread = camel_folder_get_unread_message_count(local_folder->folder);
+ }
+
camel_object_unref (CAMEL_OBJECT (store));
free_metainfo (meta);
}
@@ -837,15 +451,8 @@ cleanup_register_folder (gpointer in_data, gpointer op_data, CamelException *ex)
return;
}
- g_hash_table_insert (local_folder->local_store->folders, local_folder->name, local_folder);
- local_folder->name = strrchr (local_folder->path, '/') + 1;
+ g_hash_table_insert (local_folder->local_store->folders, local_folder->uri + 8, local_folder);
- camel_object_hook_event (CAMEL_OBJECT (local_folder->folder),
- "folder_changed", local_folder_changed_proxy,
- local_folder);
- camel_object_hook_event (CAMEL_OBJECT (local_folder->folder),
- "message_changed", local_folder_changed_proxy,
- local_folder);
unread = local_folder->last_unread;
local_folder->last_unread = 0;
local_folder_changed (CAMEL_OBJECT (local_folder->folder), GINT_TO_POINTER (unread), local_folder);
@@ -876,8 +483,9 @@ local_storage_new_folder_cb (EvolutionStorageListener *storage_listener,
return;
local_folder = g_new0 (MailLocalFolder, 1);
- local_folder->name = g_strdup (folder->physical_uri + 8);
+ local_folder->name = g_strdup (strrchr (path, '/') + 1);
local_folder->path = g_strdup (path);
+ local_folder->uri = g_strdup (folder->physical_uri);
local_folder->local_store = local_store;
camel_object_ref((CamelObject *)local_store);
@@ -921,9 +529,7 @@ local_storage_removed_folder_cb (EvolutionStorageListener *storage_listener,
local_store->local_pathlen) != 0)
return;
- path += 7 + local_store->local_pathlen;
-
- local_folder = g_hash_table_lookup (local_store->folders, path);
+ local_folder = g_hash_table_lookup (local_store->folders, path + 8);
if (local_folder) {
g_hash_table_remove (local_store->folders, path);
free_local_folder(local_folder);
@@ -949,24 +555,10 @@ non_equal (gconstpointer a, gconstpointer b)
return TRUE;
}
-CamelFolder *
-mail_local_lookup_folder (const char *name,
- CamelException *ev)
-{
- MailLocalStore *local_store;
-
- local_store = (MailLocalStore *)camel_session_get_service (session,
- "file:/",
- CAMEL_PROVIDER_STORE, NULL);
-
- return get_folder (CAMEL_STORE(local_store), name, 0, ev);
-}
-
void
mail_local_storage_startup (EvolutionShellClient *shellclient,
const char *evolution_path)
{
- MailLocalStore *local_store;
GNOME_Evolution_StorageListener corba_local_storage_listener;
CORBA_Environment ev;
@@ -1029,3 +621,317 @@ mail_local_storage_startup (EvolutionShellClient *shellclient,
}
CORBA_exception_free (&ev);
}
+
+
+/* Local folder reconfiguration stuff */
+
+/*
+ open new
+ copy old->new
+ close old
+ rename old oldsave
+ rename new old
+ open oldsave
+ delete oldsave
+
+ close old
+ rename oldtmp
+ open new
+ open oldtmp
+ copy oldtmp new
+ close oldtmp
+ close oldnew
+
+*/
+
+static void
+update_progress(char *fmt, float percent)
+{
+ if (fmt)
+ mail_status(fmt);
+ /*mail_op_set_percentage (percent);*/
+}
+
+/* ******************** */
+
+typedef struct reconfigure_folder_input_s {
+ FolderBrowser *fb;
+ gchar *newtype;
+ GtkWidget *frame;
+ GtkWidget *apply;
+ GtkWidget *cancel;
+ GtkOptionMenu *optionlist;
+} reconfigure_folder_input_t;
+
+static gchar *
+describe_reconfigure_folder (gpointer in_data, gboolean gerund)
+{
+ reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data;
+
+ if (gerund)
+ return g_strdup_printf (_("Changing folder \"%s\" to \"%s\" format"),
+ input->fb->uri,
+ input->newtype);
+ else
+ return g_strdup_printf (_("Change folder \"%s\" to \"%s\" format"),
+ input->fb->uri,
+ input->newtype);
+}
+
+static void
+setup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex)
+{
+ reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data;
+
+ gtk_object_ref (GTK_OBJECT (input->fb));
+}
+
+static void
+do_reconfigure_folder(gpointer in_data, gpointer op_data, CamelException *ex)
+{
+ reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data;
+ MailLocalFolder *local_folder;
+ CamelStore *fromstore = NULL, *tostore = NULL;
+ char *fromurl = NULL, *tourl = NULL;
+ CamelFolder *fromfolder = NULL, *tofolder = NULL;
+ GPtrArray *uids;
+ int i;
+ char *metapath;
+ char *tmpname;
+ CamelURL *url = NULL;
+ struct _local_meta *meta;
+ guint32 flags;
+
+ d(printf("reconfiguring folder: %s to type %s\n", input->fb->uri, input->newtype));
+
+ mail_status_start(_("Reconfiguring folder"));
+
+ /* NOTE: This var is cleared by the folder_browser via the set_uri method */
+ input->fb->reconfigure = TRUE;
+
+ /* get the actual location of the mailbox */
+ url = camel_url_new(input->fb->uri, ex);
+ if (camel_exception_is_set(ex)) {
+ g_warning("%s is not a workable url!", input->fb->uri);
+ goto cleanup;
+ }
+
+ tmpname = strchr (input->fb->uri, '/');
+ if (tmpname) {
+ while (*tmpname == '/')
+ tmpname++;
+ local_folder = g_hash_table_lookup (local_store->folders, tmpname);
+ } else
+ local_folder = NULL;
+ if (!local_folder) {
+ g_warning("%s is not a registered local folder!", input->fb->uri);
+ goto cleanup;
+ }
+
+ metapath = g_strdup_printf("%s/local-metadata.xml", url->path);
+ meta = load_metainfo(metapath);
+ g_free(metapath);
+
+ /* first, 'close' the old folder */
+ update_progress(_("Closing current folder"), 0.0);
+ camel_folder_sync(local_folder->folder, FALSE, ex);
+ camel_object_unhook_event(CAMEL_OBJECT (local_folder->folder),
+ "folder_changed", local_folder_changed_proxy,
+ local_folder);
+ camel_object_unhook_event(CAMEL_OBJECT (local_folder->folder),
+ "message_changed", local_folder_changed_proxy,
+ local_folder);
+ /* Once for the FolderBrowser, once for the local store */
+ camel_object_unref(CAMEL_OBJECT(local_folder->folder));
+ camel_object_unref(CAMEL_OBJECT(local_folder->folder));
+ local_folder->folder = input->fb->folder = NULL;
+
+ camel_url_set_protocol (url, meta->format);
+ fromurl = camel_url_to_string (url, FALSE);
+ camel_url_set_protocol (url, input->newtype);
+ tourl = camel_url_to_string (url, FALSE);
+
+ d(printf("opening stores %s and %s\n", fromurl, tourl));
+
+ fromstore = camel_session_get_store(session, fromurl, ex);
+
+ if (camel_exception_is_set(ex))
+ goto cleanup;
+
+ tostore = camel_session_get_store(session, tourl, ex);
+ if (camel_exception_is_set(ex))
+ goto cleanup;
+
+ /* rename the old mbox and open it again, without indexing */
+ tmpname = g_strdup_printf("%s_reconfig", meta->name);
+ d(printf("renaming %s to %s, and opening it\n", meta->name, tmpname));
+ update_progress(_("Renaming old folder and opening"), 0.0);
+
+ camel_store_rename_folder(fromstore, meta->name, tmpname, ex);
+ if (camel_exception_is_set(ex)) {
+ goto cleanup;
+ }
+
+ /* we dont need to set the create flag ... or need an index if it has one */
+ fromfolder = camel_store_get_folder(fromstore, tmpname, 0, ex);
+ if (fromfolder == NULL || camel_exception_is_set(ex)) {
+ /* try and recover ... */
+ camel_exception_clear (ex);
+ camel_store_rename_folder(fromstore, tmpname, meta->name, ex);
+ goto cleanup;
+ }
+
+ /* create a new mbox */
+ d(printf("Creating the destination mbox\n"));
+ update_progress(_("Creating new folder"), 0.0);
+
+ flags = CAMEL_STORE_FOLDER_CREATE;
+ if (meta->indexed)
+ flags |= CAMEL_STORE_FOLDER_BODY_INDEX;
+ tofolder = camel_store_get_folder(tostore, meta->name, flags, ex);
+ if (tofolder == NULL || camel_exception_is_set(ex)) {
+ d(printf("cannot open destination folder\n"));
+ /* try and recover ... */
+ camel_exception_clear (ex);
+ camel_store_rename_folder(fromstore, tmpname, meta->name, ex);
+ goto cleanup;
+ }
+
+ update_progress(_("Copying messages"), 0.0);
+ uids = camel_folder_get_uids(fromfolder);
+ for (i=0;i<uids->len;i++) {
+ mail_statusf("Copying message %d of %d", i, uids->len);
+ camel_folder_move_message_to(fromfolder, uids->pdata[i], tofolder, ex);
+ if (camel_exception_is_set(ex)) {
+ camel_folder_free_uids(fromfolder, uids);
+ goto cleanup;
+ }
+ }
+ camel_folder_free_uids(fromfolder, uids);
+ camel_folder_expunge(fromfolder, ex);
+
+ d(printf("delete old mbox ...\n"));
+ camel_store_delete_folder(fromstore, tmpname, ex);
+
+ /* switch format */
+ g_free(meta->format);
+ meta->format = g_strdup(input->newtype);
+ if (save_metainfo(meta) == -1) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Cannot save folder metainfo; "
+ "you'll probably find you can't\n"
+ "open this folder anymore: %s"),
+ tourl);
+ }
+
+ cleanup:
+ if (!local_folder->folder)
+ do_register_folder (local_folder, NULL, ex);
+ if (tofolder)
+ camel_object_unref (CAMEL_OBJECT (tofolder));
+ if (fromfolder)
+ camel_object_unref (CAMEL_OBJECT (fromfolder));
+ if (fromstore)
+ camel_object_unref (CAMEL_OBJECT (fromstore));
+ if (tostore)
+ camel_object_unref (CAMEL_OBJECT (tostore));
+ free_metainfo(meta);
+ g_free(fromurl);
+ g_free(tourl);
+ if (url)
+ camel_url_free (url);
+}
+
+static void
+cleanup_reconfigure_folder (gpointer in_data, gpointer op_data, CamelException *ex)
+{
+ reconfigure_folder_input_t *input = (reconfigure_folder_input_t *) in_data;
+ char *uri;
+
+ if (camel_exception_is_set(ex)) {
+ gnome_error_dialog (_("If you can no longer open this mailbox, then\n"
+ "you may need to repair it manually."));
+ }
+
+ /* force a reload of the newly formatted folder */
+ d(printf("opening new source\n"));
+ uri = g_strdup(input->fb->uri);
+ folder_browser_set_uri(input->fb, uri);
+ g_free(uri);
+
+ mail_status_end();
+
+ gtk_object_unref (GTK_OBJECT (input->fb));
+ g_free (input->newtype);
+}
+
+static const mail_operation_spec op_reconfigure_folder =
+{
+ describe_reconfigure_folder,
+ 0,
+ setup_reconfigure_folder,
+ do_reconfigure_folder,
+ cleanup_reconfigure_folder
+};
+
+static void
+reconfigure_clicked(GnomeDialog *d, int button, reconfigure_folder_input_t *data)
+{
+ if (button == 0) {
+ GtkMenu *menu;
+ int type;
+ char *types[] = { "mbox", "maildir", "mh" };
+
+ menu = (GtkMenu *)gtk_option_menu_get_menu(data->optionlist);
+ type = g_list_index(GTK_MENU_SHELL(menu)->children, gtk_menu_get_active(menu));
+ if (type < 0 || type > 2)
+ type = 0;
+
+ gtk_widget_set_sensitive(data->frame, FALSE);
+ gtk_widget_set_sensitive(data->apply, FALSE);
+ gtk_widget_set_sensitive(data->cancel, FALSE);
+
+ data->newtype = g_strdup (types[type]);
+ mail_operation_queue (&op_reconfigure_folder, data, TRUE);
+ } else
+ g_free (data);
+
+ if (button != -1)
+ gnome_dialog_close(d);
+}
+
+void
+mail_local_reconfigure_folder(FolderBrowser *fb)
+{
+ CamelStore *store;
+ GladeXML *gui;
+ GnomeDialog *gd;
+ reconfigure_folder_input_t *data;
+
+ if (fb->folder == NULL) {
+ g_warning("Trying to reconfigure nonexistant folder");
+ return;
+ }
+
+ data = g_new (reconfigure_folder_input_t, 1);
+
+ store = camel_folder_get_parent_store(fb->folder);
+
+ gui = glade_xml_new(EVOLUTION_GLADEDIR "/local-config.glade", "dialog_format");
+ gd = (GnomeDialog *)glade_xml_get_widget (gui, "dialog_format");
+
+ data->frame = glade_xml_get_widget (gui, "frame_format");
+ data->apply = glade_xml_get_widget (gui, "apply_format");
+ data->cancel = glade_xml_get_widget (gui, "cancel_format");
+ data->optionlist = (GtkOptionMenu *)glade_xml_get_widget (gui, "option_format");
+ data->newtype = NULL;
+ data->fb = fb;
+
+ gtk_label_set_text((GtkLabel *)glade_xml_get_widget (gui, "label_format"),
+ ((CamelService *)store)->url->protocol);
+
+ gtk_signal_connect((GtkObject *)gd, "clicked", reconfigure_clicked, data);
+ gtk_object_unref((GtkObject *)gui);
+
+ gnome_dialog_run_and_close (GNOME_DIALOG (gd));
+}