/*
* 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;
}