aboutsummaryrefslogtreecommitdiffstats
path: root/shell/e-local-storage.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/e-local-storage.c')
-rw-r--r--shell/e-local-storage.c1236
1 files changed, 0 insertions, 1236 deletions
diff --git a/shell/e-local-storage.c b/shell/e-local-storage.c
deleted file mode 100644
index 8ce9f87189..0000000000
--- a/shell/e-local-storage.c
+++ /dev/null
@@ -1,1236 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-/* e-local-storage.c
- *
- * Copyright (C) 2000, 2001 Ximian, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Author: Ettore Perazzoli
- */
-
-/* FIXMEs:
- *
- * - If we have `.' or `..' as path elements, we lose.
- *
- * - If the LocalStorage is destroyed and an async operation on a shell component is
- * pending, we get a callback on a bogus object. We need support for cancelling
- * operations on the shell component.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <dirent.h>
-
-#include <gtk/gtksignal.h>
-
-#include <libgnome/gnome-i18n.h>
-#include <libgnome/gnome-util.h>
-
-#include <gal/util/e-util.h>
-
-#include "e-util/e-path.h"
-#include "e-local-folder.h"
-#include "e-shell-constants.h"
-
-#include "evolution-storage.h"
-
-#include "e-local-storage.h"
-
-#include <bonobo/bonobo-exception.h>
-
-#define PARENT_TYPE E_TYPE_STORAGE
-static EStorageClass *parent_class = NULL;
-
-struct _ELocalStoragePrivate {
- EFolderTypeRegistry *folder_type_registry;
- char *base_path;
- EvolutionStorage *bonobo_interface;
-};
-
-
-/* EStorageResult <-> errno mapping. */
-
-static EStorageResult
-errno_to_storage_result (void)
-{
- EStorageResult storage_result;
-
- switch (errno) {
- case EACCES:
- case EROFS:
- storage_result = E_STORAGE_PERMISSIONDENIED;
- break;
- case EEXIST:
- storage_result = E_STORAGE_EXISTS;
- break;
- case ENOSPC:
- storage_result = E_STORAGE_NOSPACE;
- break;
- default:
- storage_result = E_STORAGE_GENERICERROR;
- }
-
- return storage_result;
-}
-
-static EStorageResult
-shell_component_result_to_storage_result (EvolutionShellComponentResult result)
-{
- /* FIXME: Maybe we need better mapping here. */
- switch (result) {
- case EVOLUTION_SHELL_COMPONENT_OK:
- return E_STORAGE_OK;
- case EVOLUTION_SHELL_COMPONENT_NOTFOUND:
- return E_STORAGE_NOTFOUND;
- case EVOLUTION_SHELL_COMPONENT_UNSUPPORTEDTYPE:
- return E_STORAGE_UNSUPPORTEDTYPE;
- case EVOLUTION_SHELL_COMPONENT_UNSUPPORTEDOPERATION:
- return E_STORAGE_UNSUPPORTEDOPERATION;
- case EVOLUTION_SHELL_COMPONENT_EXISTS:
- return E_STORAGE_EXISTS;
- case EVOLUTION_SHELL_COMPONENT_PERMISSIONDENIED:
- return E_STORAGE_PERMISSIONDENIED;
- case EVOLUTION_SHELL_COMPONENT_ALREADYOWNED:
- case EVOLUTION_SHELL_COMPONENT_BUSY:
- case EVOLUTION_SHELL_COMPONENT_CORBAERROR:
- case EVOLUTION_SHELL_COMPONENT_HASSUBFOLDERS:
- case EVOLUTION_SHELL_COMPONENT_INTERNALERROR:
- case EVOLUTION_SHELL_COMPONENT_INTERRUPTED:
- case EVOLUTION_SHELL_COMPONENT_INVALIDARG:
- case EVOLUTION_SHELL_COMPONENT_INVALIDURI:
- case EVOLUTION_SHELL_COMPONENT_NOSPACE:
- case EVOLUTION_SHELL_COMPONENT_NOTOWNED:
- case EVOLUTION_SHELL_COMPONENT_UNKNOWNERROR:
- default:
- return E_STORAGE_GENERICERROR;
- }
-}
-
-
-/* Utility functions. */
-
-static void
-new_folder (ELocalStorage *local_storage,
- const char *path,
- EFolder *folder)
-{
- ELocalStoragePrivate *priv;
-
- priv = local_storage->priv;
-
- e_storage_new_folder (E_STORAGE (local_storage), path, folder);
-
- evolution_storage_new_folder (EVOLUTION_STORAGE (priv->bonobo_interface),
- path,
- e_folder_get_name (folder),
- e_folder_get_type_string (folder),
- e_folder_get_physical_uri (folder),
- e_folder_get_description (folder),
- e_folder_get_custom_icon_name (folder),
- e_folder_get_unread_count (folder),
- FALSE,
- 0);
-}
-
-static gboolean
-setup_folder_as_stock (ELocalStorage *local_storage,
- const char *path,
- const char *name,
- const char *custom_icon_name)
-{
- EFolder *folder;
-
- folder = e_storage_get_folder (E_STORAGE (local_storage), path);
- if (folder == NULL)
- return FALSE;
-
- e_folder_set_name (folder, name);
- e_folder_set_is_stock (folder, TRUE);
- e_folder_set_custom_icon (folder, custom_icon_name);
-
- return TRUE;
-}
-
-static void
-setup_stock_folders (ELocalStorage *local_storage)
-{
- setup_folder_as_stock (local_storage, "/Calendar", _("Calendar"), NULL);
- setup_folder_as_stock (local_storage, "/Contacts", _("Contacts"), NULL);
- setup_folder_as_stock (local_storage, "/Drafts", _("Drafts"), NULL);
- setup_folder_as_stock (local_storage, "/Inbox", _("Inbox"), "inbox");
- setup_folder_as_stock (local_storage, "/Outbox", _("Outbox"), "outbox");
- setup_folder_as_stock (local_storage, "/Sent", _("Sent"), NULL);
- setup_folder_as_stock (local_storage, "/Tasks", _("Tasks"), NULL);
- setup_folder_as_stock (local_storage, "/Trash", _("Trash"), NULL);
-}
-
-static gboolean
-load_folder (const char *physical_path,
- const char *path,
- void *data)
-{
- ELocalStorage *local_storage;
- EFolder *folder;
-
- local_storage = E_LOCAL_STORAGE (data);
-
- folder = e_local_folder_new_from_path (physical_path);
- if (folder == NULL) {
- /* g_warning ("No folder metadata in %s... ignoring", physical_path); FIXME */
- return TRUE;
- }
-
- e_storage_new_folder ((EStorage *)local_storage, path, folder);
- return TRUE;
-}
-
-static void
-setup_corba_storage (ELocalStorage *local_storage,
- const char *path)
-{
- GList *subfolder_paths;
- EFolder *folder;
- GList *p;
-
- folder = e_storage_get_folder (E_STORAGE (local_storage), path);
-
- if (folder != NULL)
- evolution_storage_new_folder (EVOLUTION_STORAGE (local_storage->priv->bonobo_interface),
- path,
- e_folder_get_name (folder),
- e_folder_get_type_string (folder),
- e_folder_get_physical_uri (folder),
- e_folder_get_description (folder),
- e_folder_get_custom_icon_name (folder),
- e_folder_get_unread_count (folder),
- FALSE,
- 0);
-
- subfolder_paths = e_storage_get_subfolder_paths (E_STORAGE (local_storage), path);
-
- for (p = subfolder_paths; p != NULL; p = p->next)
- setup_corba_storage (local_storage, (const char *) p->data);
-
- e_free_string_list (subfolder_paths);
-}
-
-static gboolean
-load_all_folders (ELocalStorage *local_storage)
-{
- const char *base_path;
-
- base_path = e_local_storage_get_base_path (local_storage);
-
- /* Ignore errors, so we set up the local storage even if there is stale
- data that we don't understand in ~/evolution. */
- e_path_find_folders (base_path, load_folder, local_storage);
-
- setup_stock_folders (local_storage);
-
- setup_corba_storage (local_storage, "/");
-
- return TRUE;
-}
-
-static EStorageResult
-storage_result_from_component_result (EvolutionShellComponentResult result)
-{
- switch (result) {
- case EVOLUTION_SHELL_COMPONENT_PERMISSIONDENIED:
- return E_STORAGE_PERMISSIONDENIED;
- case EVOLUTION_SHELL_COMPONENT_NOSPACE:
- return E_STORAGE_NOSPACE;
- default:
- return E_STORAGE_GENERICERROR;
- }
-}
-
-
-/* Callbacks for the async methods invoked on the `Evolution::ShellComponent's. */
-
-static void
-notify_listener (const Bonobo_Listener listener,
- EStorageResult result,
- const char *physical_path)
-{
- CORBA_any any;
- GNOME_Evolution_Storage_FolderResult folder_result;
- CORBA_Environment ev;
-
- folder_result.result = result;
- folder_result.path = CORBA_string_dup (physical_path ? physical_path : "");
- any._type = TC_GNOME_Evolution_Storage_FolderResult;
- any._value = &folder_result;
-
- CORBA_exception_init (&ev);
- Bonobo_Listener_event (listener, "evolution-shell:folder_created",
- &any, &ev);
- if (BONOBO_EX (&ev)) {
- g_warning ("Exception notifing listener: %s\n",
- CORBA_exception_id (&ev));
- }
- CORBA_exception_free (&ev);
-}
-
-struct _AsyncCreateFolderCallbackData {
- EStorage *storage;
- Bonobo_Listener listener;
-
- char *path;
- char *display_name;
- char *type;
- char *description;
- char *physical_uri;
- char *physical_path;
-
- EStorageResultCallback callback;
- void *callback_data;
-};
-typedef struct _AsyncCreateFolderCallbackData AsyncCreateFolderCallbackData;
-
-static void
-component_async_create_folder_callback (EvolutionShellComponentClient *shell_component_client,
- EvolutionShellComponentResult result,
- void *data)
-{
- AsyncCreateFolderCallbackData *callback_data;
- EStorageResult storage_result;
-
- callback_data = (AsyncCreateFolderCallbackData *) data;
-
- storage_result = shell_component_result_to_storage_result (result);
-
- if (result != EVOLUTION_SHELL_COMPONENT_OK) {
- /* XXX: This assumes the component won't leave any files in the directory. */
- rmdir (callback_data->physical_path);
- } else {
- EFolder *folder;
-
- folder = e_local_folder_new (callback_data->display_name,
- callback_data->type,
- callback_data->description);
-
- e_folder_set_physical_uri (folder, callback_data->physical_uri);
-
- if (e_local_folder_save (E_LOCAL_FOLDER (folder))) {
- new_folder (E_LOCAL_STORAGE (callback_data->storage),
- callback_data->path, folder);
- } else {
- rmdir (callback_data->physical_path);
- g_object_unref (folder);
- storage_result = E_STORAGE_IOERROR;
- }
- }
-
- g_object_unref (shell_component_client);
-
- if (callback_data->listener != CORBA_OBJECT_NIL)
- notify_listener (callback_data->listener, storage_result,
- callback_data->physical_path);
-
- if (callback_data->callback != NULL)
- (* callback_data->callback) (callback_data->storage,
- storage_result,
- callback_data->callback_data);
-
- g_free (callback_data->path);
- g_free (callback_data->display_name);
- g_free (callback_data->type);
- g_free (callback_data->description);
- g_free (callback_data->physical_uri);
- g_free (callback_data->physical_path);
- g_free (callback_data);
-}
-
-
-/* Implementation for the folder operations. */
-
-static EStorageResult
-create_folder_directory (ELocalStorage *local_storage,
- const char *path,
- const char *type,
- const char *description,
- char **physical_path_return)
-{
- EStorage *storage;
- ELocalStoragePrivate *priv;
- char *parent_path;
- char *physical_path;
-
- storage = E_STORAGE (local_storage);
- priv = local_storage->priv;
-
- *physical_path_return = NULL;
- g_assert (g_path_is_absolute (path));
-
- parent_path = g_path_get_dirname(path);
-
- if (strlen(parent_path) > 1) {
- char *subfolders_directory_physical_path;
- char *parent;
-
- /* Create the `subfolders' subdirectory under the parent. */
- parent = g_strdup_printf ("%s/", parent_path);
- subfolders_directory_physical_path = e_path_to_physical (priv->base_path, parent);
-
- if (mkdir (subfolders_directory_physical_path, 0700) == -1 && errno != EEXIST) {
- g_free (subfolders_directory_physical_path);
- g_free (parent);
- return errno_to_storage_result ();
- }
-
- g_free (subfolders_directory_physical_path);
- g_free (parent);
- }
-
- g_free (parent_path);
-
- physical_path = e_path_to_physical (priv->base_path, path);
-
- /* Create the directory that holds the folder. */
-
- *physical_path_return = physical_path;
- if (mkdir (physical_path, 0700) == -1) {
- return errno_to_storage_result ();
- }
-
- return E_STORAGE_OK;
-}
-
-static void
-create_folder (ELocalStorage *local_storage,
- const Bonobo_Listener listener,
- const char *path,
- const char *type,
- const char *description,
- EStorageResultCallback callback,
- void *data)
-{
- EStorage *storage;
- ELocalStoragePrivate *priv;
- EvolutionShellComponentClient *component_client;
- AsyncCreateFolderCallbackData *callback_data;
- EStorageResult result;
- char *folder_name;
- char *physical_path;
- char *physical_uri;
-
- storage = E_STORAGE (local_storage);
- priv = local_storage->priv;
- component_client = e_folder_type_registry_get_handler_for_type (priv->folder_type_registry,
- type);
- if (component_client == NULL) {
- if (listener != CORBA_OBJECT_NIL)
- notify_listener (listener, E_STORAGE_INVALIDTYPE, NULL);
- if (callback != NULL)
- (* callback) (storage, E_STORAGE_INVALIDTYPE, data);
- return;
- }
-
- g_assert (g_path_is_absolute (path));
-
- result = create_folder_directory (local_storage, path, type, description, &physical_path);
- if (result != E_STORAGE_OK) {
- if (callback != NULL)
- (* callback) (storage, result, data);
- if (listener != CORBA_OBJECT_NIL)
- notify_listener (listener, result, NULL);
-
- g_free (physical_path);
- return;
- }
-
- folder_name = g_path_get_basename (path);
-
- /* Finally tell the component to do the job of creating the physical files in it. */
-
- /* FIXME: We should put the operations on a queue so that we can cancel them when
- the ELocalStorage is destroyed. */
-
- physical_uri = g_strconcat ("file://", physical_path, NULL);
-
- callback_data = g_new (AsyncCreateFolderCallbackData, 1);
- callback_data->storage = E_STORAGE (local_storage);
- callback_data->path = g_strdup (path);
- callback_data->display_name = g_strdup (folder_name);
- callback_data->type = g_strdup (type);
- callback_data->description = g_strdup (description);
- callback_data->physical_uri = physical_uri;
- callback_data->physical_path = physical_path;
- callback_data->listener = listener;
- callback_data->callback = callback;
- callback_data->callback_data = data;
-
- g_object_ref (component_client);
-
- evolution_shell_component_client_async_create_folder (component_client,
- physical_uri,
- type,
- component_async_create_folder_callback,
- callback_data);
-
- g_free (folder_name);
-}
-
-struct _AsyncRemoveFolderCallbackData {
- EStorage *storage;
- GList *next_paths_to_delete;
-};
-typedef struct _AsyncRemoveFolderCallbackData AsyncRemoveFolderCallbackData;
-
-static EStorageResult
-remove_folder_directory (ELocalStorage *local_storage,
- const char *path)
-{
- EStorage *storage;
- ELocalStoragePrivate *priv;
- char *folder_name;
- char *file_name;
- char *physical_path;
-
- priv = local_storage->priv;
-
- storage = E_STORAGE (local_storage);
- folder_name = g_path_get_basename (path);
-
- /* Delete the metadata file associated with this folder. */
- physical_path = e_path_to_physical (priv->base_path, path);
- file_name = g_build_filename (physical_path, E_LOCAL_FOLDER_METADATA_FILE_NAME, NULL);
- unlink (file_name);
- g_free (file_name);
-
- /* Delete the physical directory. */
- if (rmdir (physical_path) == -1) {
- g_free (physical_path);
- g_free (folder_name);
- return E_STORAGE_GENERICERROR;
- }
-
- g_free (physical_path);
-
- /* Delete the 'subfolders' directory that this folder lies in */
- if (folder_name != path + 1) {
- char *subfolders_directory_physical_path;
- char *parent_path;
-
- parent_path = g_strndup (path, strlen (path) - strlen (folder_name));
- subfolders_directory_physical_path = e_path_to_physical (priv->base_path, parent_path);
- g_free (parent_path);
-
- rmdir (subfolders_directory_physical_path);
- g_free (subfolders_directory_physical_path);
- }
-
- g_free (folder_name);
- return E_STORAGE_OK;
-}
-
-static gboolean remove_folder_step (AsyncRemoveFolderCallbackData *callback_data);
-
-static void
-component_async_remove_folder_callback (EvolutionShellComponentClient *shell_component_client,
- EvolutionShellComponentResult result,
- void *data)
-{
- ELocalStoragePrivate *priv;
- AsyncRemoveFolderCallbackData *callback_data;
- EStorageResult storage_result;
- gboolean success;
- const char *path;
-
- callback_data = (AsyncRemoveFolderCallbackData *) data;
- priv = E_LOCAL_STORAGE (callback_data->storage)->priv;
- path = (const char *) callback_data->next_paths_to_delete->data;
-
- storage_result = shell_component_result_to_storage_result (result);
-
- if (result == EVOLUTION_SHELL_COMPONENT_OK) {
- result = remove_folder_directory (E_LOCAL_STORAGE (callback_data->storage), path);
- e_storage_removed_folder (E_STORAGE (callback_data->storage), path);
- evolution_storage_removed_folder (EVOLUTION_STORAGE (priv->bonobo_interface), path);
- } else {
- /* FIXME: Handle errors. */
- g_print ("...Error removing %s!\n", path);
- }
-
- g_object_unref (shell_component_client);
-
- /* Now go on and delete the next subfolder in the list that still
- exists, deallocating the elements in the list in the process. */
- do {
- char *path;
-
- path = callback_data->next_paths_to_delete->data;
- g_free (path);
-
- callback_data->next_paths_to_delete
- = g_list_remove_link (callback_data->next_paths_to_delete,
- callback_data->next_paths_to_delete);
-
- /* Check if we are done. */
- if (callback_data->next_paths_to_delete == NULL) {
- g_free (callback_data);
- return;
- }
-
- /* Remove the folder; if the folder has disappeared from the
- tree for some reason (this is an async callback!), just go
- on with the next one. */
- success = remove_folder_step (callback_data);
- } while (! success);
-}
-
-static gboolean
-remove_folder_step (AsyncRemoveFolderCallbackData *callback_data)
-{
- EvolutionShellComponentClient *client;
- ELocalStoragePrivate *priv;
- EFolder *folder;
- const char *path;
- const char *type;
- char *physical_path;
- char *physical_uri;
-
- g_assert (callback_data->next_paths_to_delete != NULL);
- path = (const char *) callback_data->next_paths_to_delete->data;
-
- folder = e_storage_get_folder (callback_data->storage, path);
- if (folder == NULL)
- return FALSE;
-
- priv = E_LOCAL_STORAGE (callback_data->storage)->priv;
-
- physical_path = e_path_to_physical (priv->base_path, path);
- physical_uri = g_strconcat ("file://", physical_path, NULL);
-
- type = e_folder_get_type_string (folder);
- client = e_folder_type_registry_get_handler_for_type (priv->folder_type_registry, type);
-
- g_object_ref (client);
-
- evolution_shell_component_client_async_remove_folder (client, physical_uri, type,
- component_async_remove_folder_callback,
- callback_data);
-
- g_free (physical_path);
- g_free (physical_uri);
-
- return TRUE;
-}
-
-static GList *
-create_subfolder_list (ELocalStorage *local_storage,
- const char *path)
-{
- GList *subfolders;
- GList *list;
- GList *p;
-
- subfolders = e_storage_get_subfolder_paths (E_STORAGE (local_storage), path);
-
- list = NULL;
- for (p = subfolders; p != NULL; p = p->next) {
- char *path;
-
- path = (char *) p->data;
-
- list = g_list_concat (list, create_subfolder_list (local_storage, path));
- list = g_list_append (list, path);
- }
-
- g_list_free (subfolders);
-
- return list;
-}
-
-static EStorageResult
-remove_folder (ELocalStorage *local_storage,
- const char *path)
-{
- ELocalStoragePrivate *priv;
- EStorage *storage;
- AsyncRemoveFolderCallbackData *callback_data;
- EvolutionShellComponentClient *component_client;
- EFolder *folder;
- GList *next_paths_to_delete;
-
- priv = local_storage->priv;
-
- storage = E_STORAGE (local_storage);
- folder = e_storage_get_folder (storage, path);
-
- if (e_folder_get_is_stock (folder))
- return E_STORAGE_CANTCHANGESTOCKFOLDER;
-
- component_client = e_folder_type_registry_get_handler_for_type (priv->folder_type_registry,
- e_folder_get_type_string (folder));
- if (component_client == NULL)
- return E_STORAGE_INVALIDTYPE;
-
- next_paths_to_delete = create_subfolder_list (E_LOCAL_STORAGE (storage), path);
- next_paths_to_delete = g_list_append (next_paths_to_delete, g_strdup (path));
-
- callback_data = g_new (AsyncRemoveFolderCallbackData, 1);
- callback_data->storage = E_STORAGE (local_storage);
- callback_data->next_paths_to_delete = next_paths_to_delete;
-
- if (! remove_folder_step (callback_data)) {
- /* Eek, something wacky happened. */
- return EVOLUTION_SHELL_COMPONENT_UNKNOWNERROR;
- }
-
- return EVOLUTION_SHELL_COMPONENT_OK;
-}
-
-
-/* GtkObject methods. */
-
-static void
-impl_dispose (GObject *object)
-{
- ELocalStorage *local_storage;
- ELocalStoragePrivate *priv;
- CORBA_Environment ev;
-
- local_storage = E_LOCAL_STORAGE (object);
- priv = local_storage->priv;
-
- CORBA_exception_init (&ev);
-
- if (priv->folder_type_registry != NULL) {
- g_object_unref (priv->folder_type_registry);
- priv->folder_type_registry = NULL;
- }
-
- if (priv->bonobo_interface != NULL) {
- bonobo_object_unref (BONOBO_OBJECT (priv->bonobo_interface));
- priv->bonobo_interface = NULL;
- }
-
- CORBA_exception_free (&ev);
-
- (* G_OBJECT_CLASS (parent_class)->dispose) (object);
-}
-
-static void
-impl_finalize (GObject *object)
-{
- ELocalStorage *local_storage;
- ELocalStoragePrivate *priv;
-
- local_storage = E_LOCAL_STORAGE (object);
- priv = local_storage->priv;
-
- g_free (priv->base_path);
- g_free (priv);
-
- (* G_OBJECT_CLASS (parent_class)->finalize) (object);
-}
-
-
-/* Creating folders. */
-
-static void
-impl_async_create_folder (EStorage *storage,
- const char *path,
- const char *type,
- const char *description,
- EStorageResultCallback callback,
- void *data)
-{
- ELocalStorage *local_storage;
-
- local_storage = E_LOCAL_STORAGE (storage);
-
- create_folder (local_storage, CORBA_OBJECT_NIL, path, type, description, callback, data);
-}
-
-
-/* Removing folders. */
-
-static void
-impl_async_remove_folder (EStorage *storage,
- const char *path,
- EStorageResultCallback callback,
- void *data)
-{
- ELocalStorage *local_storage;
- EStorageResult result;
-
- local_storage = E_LOCAL_STORAGE (storage);
-
- result = remove_folder (local_storage, path);
-
- if (callback != NULL)
- (* callback) (E_STORAGE (local_storage), result, data);
-}
-
-
-
-/* Transferring folders. */
-
-struct _XferItem {
- char *source_path;
- char *destination_path;
-};
-typedef struct _XferItem XferItem;
-
-static XferItem *
-xfer_item_new (char *source_path,
- char *destination_path)
-{
- XferItem *new;
-
- new = g_new (XferItem, 1);
- new->source_path = source_path;
- new->destination_path = destination_path;
-
- return new;
-}
-
-static void
-xfer_item_free (XferItem *item)
-{
- g_free (item->source_path);
- g_free (item->destination_path);
- g_free (item);
-}
-
-static void
-append_xfer_item_list (EStorage *storage,
- char *source_path,
- char *destination_path,
- GList **list)
-{
- GList *subfolders;
- GList *p;
-
- *list = g_list_prepend (*list, xfer_item_new (source_path, destination_path));
-
- subfolders = e_storage_get_subfolder_paths (storage, source_path);
- for (p = subfolders; p != NULL; p = p->next) {
- char *base_name;
- char *source_subpath;
- char *destination_subpath;
-
- source_subpath = g_strdup ((const char *) p->data);
- base_name = g_path_get_basename (source_subpath);
- destination_subpath = g_build_filename (destination_path, base_name, NULL);
- append_xfer_item_list (storage, source_subpath, destination_subpath, list);
- g_free (base_name);
- }
-
- e_free_string_list (subfolders);
-}
-
-struct _XferData {
- /* The storage on which we are performing the xfer operation. */
- ELocalStorage *local_storage;
-
- /* List of source/destination path couples to copy, in the right
- order. */
- GList *folder_items;
-
- /* Pointer into `folder_items'. The folder item pointed by this is the
- one handled by the previous CORBA invocation. */
- GList *current_folder_item;
-
- /* Whether we want to remove the source too. */
- gboolean remove_source;
-
- /* The callback, with its data. */
- EStorageResultCallback callback;
- void *callback_data;
-};
-typedef struct _XferData XferData;
-
-static void
-async_xfer_folder_step (ELocalStorage *local_storage,
- const char *source_path,
- const char *destination_path,
- gboolean remove_source,
- EvolutionShellComponentClientCallback component_client_callback,
- void *component_client_callback_data)
-{
- ELocalStoragePrivate *priv;
- EFolder *source_folder;
- EvolutionShellComponentClient *component_client;
- char *physical_path;
- char *physical_uri;
-
- priv = local_storage->priv;
-
- source_folder = e_storage_get_folder (E_STORAGE (local_storage), source_path);
- g_assert (source_folder != NULL);
-
- create_folder_directory (local_storage, destination_path,
- e_folder_get_type_string (source_folder),
- e_folder_get_description (source_folder),
- &physical_path);
-
- physical_uri = g_strconcat ("file://", physical_path, NULL);
- g_free (physical_path);
-
- component_client = e_folder_type_registry_get_handler_for_type (priv->folder_type_registry,
- e_folder_get_type_string (source_folder));
- g_assert (component_client != NULL);
-
- evolution_shell_component_client_async_xfer_folder (component_client,
- e_folder_get_physical_uri (source_folder),
- physical_uri,
- e_folder_get_type_string (source_folder),
- remove_source,
- component_client_callback,
- component_client_callback_data);
- g_free (physical_uri);
-}
-
-static void
-async_xfer_folder_complete (XferData *xfer_data,
- gboolean success)
-{
- ELocalStorage *local_storage;
- GList *p;
-
- local_storage = xfer_data->local_storage;
-
- if (success && xfer_data->remove_source) {
- EStorageResult result;
-
- /* Remove all the source physical directories, and also the
- corresponding folders from the folder tree. */
-
- for (p = g_list_last (xfer_data->folder_items); p != NULL; p = p->prev) {
- XferItem *item;
-
- item = (XferItem *) p->data;
-
- result = remove_folder_directory (local_storage, item->source_path);
-
- /* FIXME handle failure differently? This should be n
- unlikely situation. */
- if (result == E_STORAGE_OK) {
- e_storage_removed_folder (E_STORAGE (local_storage), item->source_path);
-
- evolution_storage_removed_folder (EVOLUTION_STORAGE (local_storage->priv->bonobo_interface),
- item->source_path);
- }
- }
- }
-
- /* Free the data. */
-
- for (p = xfer_data->folder_items; p != NULL; p = p->next) {
- XferItem *item;
-
- item = (XferItem *) p->data;
- xfer_item_free (item);
- }
- g_list_free (xfer_data->folder_items);
-
- g_free (xfer_data);
-}
-
-static void
-async_xfer_folder_callback (EvolutionShellComponentClient *shell_component_client,
- EvolutionShellComponentResult result,
- void *callback_data)
-{
- XferData *xfer_data;
- XferItem *item;
- EFolder *source_folder;
- EFolder *destination_folder;
- char *dest_physical_path;
- char *new_physical_uri;
-
- xfer_data = (XferData *) callback_data;
-
- item = (XferItem *) xfer_data->current_folder_item->data;
-
- if (result != EVOLUTION_SHELL_COMPONENT_OK) {
- (* xfer_data->callback) (E_STORAGE (xfer_data->local_storage),
- storage_result_from_component_result (result),
- xfer_data->callback_data);
- async_xfer_folder_complete (xfer_data, FALSE);
- return;
- }
-
- source_folder = e_storage_get_folder (E_STORAGE (xfer_data->local_storage), item->source_path);
- destination_folder = e_local_folder_new (e_folder_get_name (source_folder),
- e_folder_get_type_string (source_folder),
- e_folder_get_description (source_folder));
-
- dest_physical_path = e_path_to_physical (xfer_data->local_storage->priv->base_path, item->destination_path);
- new_physical_uri = g_strconcat ("file://", dest_physical_path, NULL);
- g_free (dest_physical_path);
- e_folder_set_physical_uri (destination_folder, new_physical_uri);
- g_free (new_physical_uri);
-
- e_local_folder_save (E_LOCAL_FOLDER (destination_folder)); /* FIXME check for errors */
- new_folder (xfer_data->local_storage, item->destination_path, destination_folder);
-
- xfer_data->current_folder_item = xfer_data->current_folder_item->next;
- if (xfer_data->current_folder_item == NULL) {
- (* xfer_data->callback) (E_STORAGE (xfer_data->local_storage), E_STORAGE_OK, xfer_data->callback_data);
- async_xfer_folder_complete (xfer_data, TRUE);
- return;
- }
-
- item = (XferItem *) xfer_data->current_folder_item->data;
-
- async_xfer_folder_step (xfer_data->local_storage,
- item->source_path,
- item->destination_path,
- xfer_data->remove_source,
- async_xfer_folder_callback,
- xfer_data);
-}
-
-static void
-impl_async_xfer_folder (EStorage *storage,
- const char *source_path,
- const char *destination_path,
- gboolean remove_source,
- EStorageResultCallback callback,
- void *callback_data)
-{
- ELocalStorage *local_storage;
- ELocalStoragePrivate *priv;
- XferData *xfer_data;
- GList *folder_items; /* <XferItem> */
- XferItem *first_item;
-
- local_storage = E_LOCAL_STORAGE (storage);
- priv = local_storage->priv;
-
- if (remove_source && e_folder_get_is_stock (e_storage_get_folder (storage, source_path))) {
- (* callback) (storage, E_STORAGE_CANTCHANGESTOCKFOLDER, callback_data);
- return;
- }
-
- folder_items = NULL;
- append_xfer_item_list (storage, g_strdup (source_path), g_strdup (destination_path), &folder_items);
- folder_items = g_list_reverse (folder_items); /* lame */
-
- xfer_data = g_new (XferData, 1);
- xfer_data->local_storage = local_storage;
- xfer_data->folder_items = folder_items;
- xfer_data->current_folder_item = folder_items;
- xfer_data->remove_source = remove_source;
- xfer_data->callback = callback;
- xfer_data->callback_data = callback_data;
-
- first_item = (XferItem *) xfer_data->folder_items->data;
-
- async_xfer_folder_step (E_LOCAL_STORAGE (storage),
- first_item->source_path,
- first_item->destination_path,
- remove_source,
- async_xfer_folder_callback,
- xfer_data);
-}
-
-
-/* Callbacks for the `Evolution::Storage' interface we are exposing to the outside world. */
-static void
-bonobo_interface_create_folder_cb (EvolutionStorage *storage,
- const Bonobo_Listener listener,
- const char *path,
- const char *type,
- const char *description,
- const char *parent_physical_uri,
- void *data)
-{
- ELocalStorage *local_storage;
-
- local_storage = E_LOCAL_STORAGE (data);
-
- create_folder (local_storage, listener, path, type, description, NULL, NULL);
-}
-
-static int
-bonobo_interface_remove_folder_cb (EvolutionStorage *storage,
- const Bonobo_Listener listener,
- const char *path,
- const char *physical_uri,
- void *data)
-{
- ELocalStorage *local_storage;
-
- local_storage = E_LOCAL_STORAGE (data);
-
- return remove_folder (local_storage, path);
-}
-
-static void
-bonobo_interface_update_folder_cb (EvolutionStorage *storage,
- const char *path,
- int unread_count,
- void *data)
-{
- ELocalStorage *local_storage;
- EFolder *folder;
-
- local_storage = E_LOCAL_STORAGE (data);
-
- folder = e_storage_get_folder (E_STORAGE (local_storage), path);
- if (folder == NULL)
- return;
-
- e_folder_set_unread_count (folder, unread_count);
- return;
-}
-
-
-/* Initialization. */
-
-static void
-class_init (ELocalStorageClass *class)
-{
- EStorageClass *storage_class;
- GObjectClass *object_class;
-
- parent_class = g_type_class_ref(e_storage_get_type ());
-
- object_class = G_OBJECT_CLASS (class);
- storage_class = E_STORAGE_CLASS (class);
-
- object_class->finalize = impl_finalize;
- object_class->dispose = impl_dispose;
-
- storage_class->async_create_folder = impl_async_create_folder;
- storage_class->async_remove_folder = impl_async_remove_folder;
- storage_class->async_xfer_folder = impl_async_xfer_folder;
-}
-
-static void
-init (ELocalStorage *local_storage)
-{
- ELocalStoragePrivate *priv;
-
- priv = g_new (ELocalStoragePrivate, 1);
-
- priv->base_path = NULL;
- priv->folder_type_registry = NULL;
- priv->bonobo_interface = NULL;
-
- local_storage->priv = priv;
-}
-
-
-static gboolean
-construct (ELocalStorage *local_storage,
- EFolderTypeRegistry *folder_type_registry,
- const char *base_path)
-{
- ELocalStoragePrivate *priv;
- EFolder *root_folder;
- int base_path_len;
- char *uri;
-
- root_folder = e_folder_new (_("Local Folders"), "noselect", "");
- uri = g_strdup_printf("file://%s;noselect", base_path);
- e_folder_set_physical_uri(root_folder, uri);
- g_free(uri);
- e_storage_construct (E_STORAGE (local_storage),
- E_LOCAL_STORAGE_NAME,
- root_folder);
-
- priv = local_storage->priv;
-
- base_path_len = strlen (base_path);
- while (base_path_len > 0 && base_path[base_path_len - 1] == E_PATH_SEPARATOR)
- base_path_len--;
-
- g_return_val_if_fail (base_path_len != 0, FALSE);
-
- g_assert (priv->folder_type_registry == NULL);
- g_object_ref (folder_type_registry);
- priv->folder_type_registry = folder_type_registry;
-
- g_assert (priv->base_path == NULL);
- priv->base_path = g_strndup (base_path, base_path_len);
-
- g_assert (priv->bonobo_interface == NULL);
- priv->bonobo_interface = evolution_storage_new (E_LOCAL_STORAGE_NAME, FALSE);
-
- g_signal_connect (priv->bonobo_interface, "create_folder",
- G_CALLBACK (bonobo_interface_create_folder_cb),
- local_storage);
- g_signal_connect (priv->bonobo_interface, "remove_folder",
- G_CALLBACK (bonobo_interface_remove_folder_cb),
- local_storage);
- g_signal_connect (priv->bonobo_interface, "update_folder",
- G_CALLBACK (bonobo_interface_update_folder_cb),
- local_storage);
-
- return load_all_folders (local_storage);
-}
-
-EStorage *
-e_local_storage_open (EFolderTypeRegistry *folder_type_registry,
- const char *base_path)
-{
- EStorage *new;
-
- g_return_val_if_fail (folder_type_registry != NULL, NULL);
- g_return_val_if_fail (E_IS_FOLDER_TYPE_REGISTRY (folder_type_registry), NULL);
- g_return_val_if_fail (base_path != NULL, NULL);
-
- new = g_object_new (e_local_storage_get_type (), NULL);
-
- if (! construct (E_LOCAL_STORAGE (new), folder_type_registry, base_path)) {
- g_object_unref (new);
- return NULL;
- }
-
- return new;
-}
-
-const char *
-e_local_storage_get_base_path (ELocalStorage *local_storage)
-{
- g_return_val_if_fail (local_storage != NULL, NULL);
- g_return_val_if_fail (E_IS_LOCAL_STORAGE (local_storage), NULL);
-
- return local_storage->priv->base_path;
-}
-
-
-const GNOME_Evolution_Storage
-e_local_storage_get_corba_interface (ELocalStorage *local_storage)
-{
- ELocalStoragePrivate *priv;
- GNOME_Evolution_Storage corba_interface;
-
- g_return_val_if_fail (local_storage != NULL, NULL);
- g_return_val_if_fail (E_IS_LOCAL_STORAGE (local_storage), NULL);
-
- priv = local_storage->priv;
- corba_interface = bonobo_object_corba_objref (BONOBO_OBJECT (priv->bonobo_interface));
-
- return corba_interface;
-}
-
-
-E_MAKE_TYPE (e_local_storage, "ELocalStorage", ELocalStorage, class_init, init, PARENT_TYPE)