/* * e-mail-store-utils.c * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser 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 Lesser General Public License * along with this program; if not, see . * */ #include "evolution-config.h" #include "e-mail-folder-utils.h" #include "e-mail-utils.h" #include "e-mail-store-utils.h" #include typedef struct _AsyncContext AsyncContext; struct _AsyncContext { gchar *full_name; }; static void async_context_free (AsyncContext *context) { g_free (context->full_name); g_slice_free (AsyncContext, context); } gboolean e_mail_store_create_folder_sync (CamelStore *store, const gchar *full_name, GCancellable *cancellable, GError **error) { CamelFolderInfo *folder_info; gchar *copied_full_name; gchar *display_name; const gchar *parent; gboolean success = TRUE; g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE); g_return_val_if_fail (full_name != NULL, FALSE); copied_full_name = g_strdup (full_name); display_name = strrchr (copied_full_name, '/'); if (display_name == NULL) { display_name = copied_full_name; parent = ""; } else { *display_name++ = '\0'; parent = copied_full_name; } folder_info = camel_store_create_folder_sync ( store, parent, display_name, cancellable, error); g_free (copied_full_name); if (folder_info == NULL) return FALSE; if (CAMEL_IS_SUBSCRIBABLE (store)) success = camel_subscribable_subscribe_folder_sync ( CAMEL_SUBSCRIBABLE (store), full_name, cancellable, error); camel_folder_info_free (folder_info); return success; } /* Helper for e_mail_store_create_folder() */ static void mail_store_create_folder_thread (GSimpleAsyncResult *simple, GObject *source_object, GCancellable *cancellable) { AsyncContext *context; GError *local_error = NULL; context = g_simple_async_result_get_op_res_gpointer (simple); e_mail_store_create_folder_sync ( CAMEL_STORE (source_object), context->full_name, cancellable, &local_error); if (local_error != NULL) g_simple_async_result_take_error (simple, local_error); } void e_mail_store_create_folder (CamelStore *store, const gchar *full_name, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; AsyncContext *context; g_return_if_fail (CAMEL_IS_STORE (store)); g_return_if_fail (full_name != NULL); context = g_slice_new0 (AsyncContext); context->full_name = g_strdup (full_name); simple = g_simple_async_result_new ( G_OBJECT (store), callback, user_data, e_mail_store_create_folder); g_simple_async_result_set_check_cancellable (simple, cancellable); g_simple_async_result_set_op_res_gpointer ( simple, context, (GDestroyNotify) async_context_free); g_simple_async_result_run_in_thread ( simple, mail_store_create_folder_thread, io_priority, cancellable); g_object_unref (simple); } gboolean e_mail_store_create_folder_finish (CamelStore *store, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple; g_return_val_if_fail ( g_simple_async_result_is_valid ( result, G_OBJECT (store), e_mail_store_create_folder), FALSE); simple = G_SIMPLE_ASYNC_RESULT (result); /* Assume success unless a GError is set. */ return !g_simple_async_result_propagate_error (simple, error); } /* Helper for e_mail_store_go_offline() */ static void mail_store_go_offline_thread (GSimpleAsyncResult *simple, GObject *source_object, GCancellable *cancellable) { GError *local_error = NULL; e_mail_store_go_offline_sync ( CAMEL_STORE (source_object), cancellable, &local_error); if (local_error != NULL) g_simple_async_result_take_error (simple, local_error); } gboolean e_mail_store_go_offline_sync (CamelStore *store, GCancellable *cancellable, GError **error) { CamelService *service; const gchar *display_name; gboolean success = TRUE; g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE); service = CAMEL_SERVICE (store); display_name = camel_service_get_display_name (service); if (display_name == NULL || *display_name == '\0') display_name = G_OBJECT_TYPE_NAME (service); camel_operation_push_message ( cancellable, _("Disconnecting from “%s”"), display_name); if (CAMEL_IS_OFFLINE_STORE (store)) { success = camel_offline_store_set_online_sync ( CAMEL_OFFLINE_STORE (store), FALSE, cancellable, error); } else { success = camel_service_disconnect_sync ( service, TRUE, cancellable, error); } camel_operation_pop_message (cancellable); return success; } void e_mail_store_go_offline (CamelStore *store, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; g_return_if_fail (CAMEL_IS_STORE (store)); simple = g_simple_async_result_new ( G_OBJECT (store), callback, user_data, e_mail_store_go_offline); g_simple_async_result_set_check_cancellable (simple, cancellable); g_simple_async_result_run_in_thread ( simple, mail_store_go_offline_thread, io_priority, cancellable); g_object_unref (simple); } gboolean e_mail_store_go_offline_finish (CamelStore *store, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple; g_return_val_if_fail ( g_simple_async_result_is_valid ( result, G_OBJECT (store), e_mail_store_go_offline), FALSE); simple = G_SIMPLE_ASYNC_RESULT (result); /* Assume success unless a GError is set. */ return !g_simple_async_result_propagate_error (simple, error); } gboolean e_mail_store_go_online_sync (CamelStore *store, GCancellable *cancellable, GError **error) { CamelService *service; const gchar *display_name; gboolean success = TRUE; g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE); service = CAMEL_SERVICE (store); display_name = camel_service_get_display_name (service); if (display_name == NULL || *display_name == '\0') display_name = G_OBJECT_TYPE_NAME (service); camel_operation_push_message ( cancellable, _("Reconnecting to “%s”"), display_name); if (CAMEL_IS_OFFLINE_STORE (store)) success = camel_offline_store_set_online_sync ( CAMEL_OFFLINE_STORE (store), TRUE, cancellable, error); camel_operation_pop_message (cancellable); return success; } /* Helper for e_mail_store_go_online() */ static void mail_store_go_online_thread (GSimpleAsyncResult *simple, GObject *source_object, GCancellable *cancellable) { GError *local_error = NULL; e_mail_store_go_online_sync ( CAMEL_STORE (source_object), cancellable, &local_error); if (local_error != NULL) g_simple_async_result_take_error (simple, local_error); } void e_mail_store_go_online (CamelStore *store, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; g_return_if_fail (CAMEL_IS_STORE (store)); simple = g_simple_async_result_new ( G_OBJECT (store), callback, user_data, e_mail_store_go_online); g_simple_async_result_set_check_cancellable (simple, cancellable); g_simple_async_result_run_in_thread ( simple, mail_store_go_online_thread, io_priority, cancellable); g_object_unref (simple); } gboolean e_mail_store_go_online_finish (CamelStore *store, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple; g_return_val_if_fail ( g_simple_async_result_is_valid ( result, G_OBJECT (store), e_mail_store_go_online), FALSE); simple = G_SIMPLE_ASYNC_RESULT (result); /* Assume success unless a GError is set. */ return !g_simple_async_result_propagate_error (simple, error); } /* Helper for e_mail_store_prepare_for_offline() */ static void mail_store_prepare_for_offline_thread (GSimpleAsyncResult *simple, GObject *source_object, GCancellable *cancellable) { CamelService *service; const gchar *display_name; GError *local_error = NULL; service = CAMEL_SERVICE (source_object); display_name = camel_service_get_display_name (service); if (display_name == NULL || *display_name == '\0') display_name = G_OBJECT_TYPE_NAME (service); camel_operation_push_message ( cancellable, _("Preparing account “%s” for offline"), display_name); if (CAMEL_IS_OFFLINE_STORE (service)) camel_offline_store_prepare_for_offline_sync ( CAMEL_OFFLINE_STORE (service), cancellable, &local_error); if (local_error != NULL) g_simple_async_result_take_error (simple, local_error); camel_operation_pop_message (cancellable); } void e_mail_store_prepare_for_offline (CamelStore *store, gint io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *simple; g_return_if_fail (CAMEL_IS_STORE (store)); simple = g_simple_async_result_new ( G_OBJECT (store), callback, user_data, e_mail_store_prepare_for_offline); g_simple_async_result_set_check_cancellable (simple, cancellable); g_simple_async_result_run_in_thread ( simple, mail_store_prepare_for_offline_thread, io_priority, cancellable); g_object_unref (simple); } gboolean e_mail_store_prepare_for_offline_finish (CamelStore *store, GAsyncResult *result, GError **error) { GSimpleAsyncResult *simple; g_return_val_if_fail ( g_simple_async_result_is_valid ( result, G_OBJECT (store), e_mail_store_prepare_for_offline), FALSE); simple = G_SIMPLE_ASYNC_RESULT (result); /* Assume success unless a GError is set. */ return !g_simple_async_result_propagate_error (simple, error); } static gboolean mail_store_save_setup_key (CamelStore *store, ESource *source, const gchar *extension_name, const gchar *property_name, const gchar *type_id, const gchar *value) { gpointer extension; GObjectClass *klass; g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE); if (source) g_return_val_if_fail (E_IS_SOURCE (source), FALSE); g_return_val_if_fail (extension_name != NULL, FALSE); g_return_val_if_fail (property_name != NULL, FALSE); g_return_val_if_fail (value != NULL, FALSE); if (!source) return FALSE; extension = e_source_get_extension (source, extension_name); if (!extension) { g_warning ("%s: Cannot find extension '%s'", G_STRFUNC, extension_name); return FALSE; } klass = G_OBJECT_GET_CLASS (extension); g_return_val_if_fail (klass != NULL, FALSE); if (!g_object_class_find_property (klass, property_name)) { g_warning ("%s: Extension '%s' doesn't have property '%s'", G_STRFUNC, extension_name, property_name); return FALSE; } if (!type_id || g_str_equal (type_id, "s")) { g_object_set (extension, property_name, value, NULL); } else if (g_str_equal (type_id, "b")) { gboolean val; val = g_strcmp0 (value, "false") != 0 && g_strcmp0 (value, "0") != 0; g_object_set (extension, property_name, val, NULL); } else if (g_str_equal (type_id, "i")) { gint val; val = (gint) g_ascii_strtoll (value, NULL, 10); g_object_set (extension, property_name, val, NULL); } else if (g_str_equal (type_id, "f")) { gchar *folder_uri; folder_uri = e_mail_folder_uri_build (store, value); g_object_set (extension, property_name, folder_uri, NULL); g_free (folder_uri); } else { g_warning ("%s: Unknown type identifier '%s' provided", G_STRFUNC, type_id); return FALSE; } return TRUE; } gboolean e_mail_store_save_initial_setup_sync (CamelStore *store, GHashTable *save_setup, ESource *collection_source, ESource *account_source, ESource *submission_source, ESource *transport_source, gboolean write_sources, GCancellable *cancellable, GError **error) { gboolean collection_changed = FALSE; gboolean account_changed = FALSE; gboolean submission_changed = FALSE; gboolean transport_changed = FALSE; gboolean success = TRUE; GHashTableIter iter; gpointer key, value; g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE); g_return_val_if_fail (save_setup != NULL, FALSE); g_return_val_if_fail (E_IS_SOURCE (account_source), FALSE); if (!g_hash_table_size (save_setup)) return TRUE; /* The key name consists of up to four parts: Source:Extension:Property[:Type] Source can be 'Collection', 'Account', 'Submission', 'Transport', 'Backend' Extension is any extension name; it's up to the key creator to make sure the extension belongs to that particular Source. Property is a property name in the Extension. Type is an optional letter describing the type of the value; if not set, then string is used. Available values are: 'b' for boolean, 'i' for integer, 's' for string, 'f' for folder full path. All the part values are case sensitive. */ g_hash_table_iter_init (&iter, save_setup); while (g_hash_table_iter_next (&iter, &key, &value)) { gchar **keys; keys = g_strsplit (key, ":", -1); if (g_strv_length (keys) < 3 || g_strv_length (keys) > 4) { g_warning ("%s: Incorrect store setup key, expects 3 or 4 parts, but %d given in '%s'", G_STRFUNC, g_strv_length (keys), (const gchar *) key); } else if (g_str_equal (keys[0], "Collection")) { if (mail_store_save_setup_key (store, collection_source, keys[1], keys[2], keys[3], value)) collection_changed = TRUE; } else if (g_str_equal (keys[0], "Account")) { if (mail_store_save_setup_key (store, account_source, keys[1], keys[2], keys[3], value)) account_changed = TRUE; } else if (g_str_equal (keys[0], "Submission")) { if (mail_store_save_setup_key (store, submission_source, keys[1], keys[2], keys[3], value)) submission_changed = TRUE; } else if (g_str_equal (keys[0], "Transport")) { if (mail_store_save_setup_key (store, transport_source, keys[1], keys[2], keys[3], value)) transport_changed = TRUE; } else if (g_str_equal (keys[0], "Backend")) { ESource *backend_source = NULL; if (collection_source && e_source_has_extension (collection_source, keys[1])) backend_source = collection_source; else if (account_source && e_source_has_extension (account_source, keys[1])) backend_source = account_source; if (mail_store_save_setup_key (store, backend_source, keys[1], keys[2], keys[3], value)) transport_changed = TRUE; } else { g_warning ("%s: Unknown source name '%s' given in '%s'", G_STRFUNC, keys[0], (const gchar *) key); } g_strfreev (keys); } if (write_sources) { if (transport_changed && success && e_source_get_writable (transport_source)) success = e_source_write_sync (transport_source, cancellable, error); if (submission_changed && success && e_source_get_writable (submission_source)) success = e_source_write_sync (submission_source, cancellable, error); if (account_changed && success && e_source_get_writable (account_source)) success = e_source_write_sync (account_source, cancellable, error); if (collection_changed && success && e_source_get_writable (collection_source)) success = e_source_write_sync (collection_source, cancellable, error); } return success; }