Camel: Add an asynchronous API.
authorMatthew Barnes <mbarnes@redhat.com>
Thu, 23 Sep 2010 18:04:32 +0000 (14:04 -0400)
committerMatthew Barnes <mbarnes@redhat.com>
Tue, 28 Sep 2010 15:36:48 +0000 (11:36 -0400)
Add pairs of asynchronous "dispatch" and "finish" methods for most
blocking "sync" methods in Camel's public API.  All asynchronous methods
have default implementations that just call its synchronous counterpart
from a thread in GIO's thread pool (which is roughly equivalent to what
Evolution is doing from its own thread pool).

The possibility for Camel providers to implement an asynchronous
architecture by overriding the asynchronous methods exists, but first
requires some cleanup in the synchronous dispatching functions, many of
which are not "pure" in the sense that they do extra stuff before and
after calling the class method they wrap.  That extra logic needs to
somehow run as part of the class method itself, either via chaining up
from subclasses or some other means.

In simpler terms, the following invariant must hold before providers can
override asynchronous methods and expect correct behavior from Camel:

    Calling camel_foo_frobnicate_sync(foo) is equivalent to calling
    CAMEL_FOO_GET_CLASS (foo)->frobnicate_sync (foo), just with fewer
    runtime checks.

68 files changed:
camel/camel-cipher-context.c
camel/camel-cipher-context.h
camel/camel-data-wrapper.c
camel/camel-data-wrapper.h
camel/camel-db.h
camel/camel-disco-diary.c
camel/camel-disco-folder.c
camel/camel-filter-driver.c
camel/camel-folder-search.c
camel/camel-folder-summary.c
camel/camel-folder-summary.h
camel/camel-folder.c
camel/camel-folder.h
camel/camel-gpg-context.c
camel/camel-mime-message.c
camel/camel-mime-message.h
camel/camel-mime-part-utils.c
camel/camel-mime-part.c
camel/camel-mime-part.h
camel/camel-multipart-signed.c
camel/camel-net-utils.c
camel/camel-offline-folder.c
camel/camel-offline-folder.h
camel/camel-operation.c
camel/camel-operation.h
camel/camel-sasl.c
camel/camel-sasl.h
camel/camel-smime-context.c
camel/camel-store.c
camel/camel-store.h
camel/camel-transport.c
camel/camel-transport.h
camel/camel-vee-folder.c
camel/camel-vtrash-folder.c
camel/providers/groupwise/camel-groupwise-folder.c
camel/providers/groupwise/camel-groupwise-journal.c
camel/providers/groupwise/camel-groupwise-store.c
camel/providers/groupwise/camel-groupwise-transport.c
camel/providers/imap/camel-imap-folder.c
camel/providers/imap/camel-imap-folder.h
camel/providers/imap/camel-imap-journal.c
camel/providers/imapx/camel-imapx-folder.c
camel/providers/imapx/camel-imapx-server.c
camel/providers/local/camel-maildir-folder.c
camel/providers/local/camel-maildir-summary.c
camel/providers/local/camel-mbox-folder.c
camel/providers/local/camel-mbox-summary.c
camel/providers/local/camel-mh-folder.c
camel/providers/local/camel-spool-summary.c
camel/providers/nntp/camel-nntp-folder.c
camel/providers/nntp/camel-nntp-summary.c
camel/providers/pop3/camel-pop3-folder.c
camel/providers/smtp/camel-smtp-transport.c
docs/reference/camel/camel-docs.sgml
docs/reference/camel/camel-sections.txt
docs/reference/camel/tmpl/camel-cipher-context.sgml
docs/reference/camel/tmpl/camel-data-wrapper.sgml
docs/reference/camel/tmpl/camel-db.sgml
docs/reference/camel/tmpl/camel-folder-summary.sgml
docs/reference/camel/tmpl/camel-folder.sgml
docs/reference/camel/tmpl/camel-mime-message.sgml
docs/reference/camel/tmpl/camel-mime-part.sgml
docs/reference/camel/tmpl/camel-offline-folder.sgml
docs/reference/camel/tmpl/camel-operation.sgml
docs/reference/camel/tmpl/camel-sasl.sgml
docs/reference/camel/tmpl/camel-store.sgml
docs/reference/camel/tmpl/camel-transport.sgml
docs/reference/camel/tmpl/camel-unused.sgml

index 3ffa355..782e997 100644 (file)
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), CAMEL_TYPE_CIPHER_CONTEXT, CamelCipherContextPrivate))
 
+typedef struct _AsyncContext AsyncContext;
+
 struct _CamelCipherContextPrivate {
        CamelSession *session;
        GMutex *lock;
 };
 
+struct _AsyncContext {
+       /* arguments */
+       CamelCipherHash hash;
+       CamelMimePart *ipart;
+       CamelMimePart *opart;
+       CamelStream *stream;
+       GPtrArray *strings;
+       gchar *userid;
+
+       /* results */
+       CamelCipherValidity *validity;
+};
+
 enum {
        PROP_0,
        PROP_SESSION
@@ -63,6 +78,32 @@ enum {
 G_DEFINE_TYPE (CamelCipherContext, camel_cipher_context, CAMEL_TYPE_OBJECT)
 
 static void
+async_context_free (AsyncContext *async_context)
+{
+       if (async_context->ipart != NULL)
+               g_object_unref (async_context->ipart);
+
+       if (async_context->opart != NULL)
+               g_object_unref (async_context->opart);
+
+       if (async_context->stream != NULL)
+               g_object_unref (async_context->stream);
+
+       if (async_context->strings != NULL) {
+               g_ptr_array_foreach (
+                       async_context->strings, (GFunc) g_free, NULL);
+               g_ptr_array_free (async_context->strings, TRUE);
+       }
+
+       if (async_context->validity != NULL)
+               camel_cipher_validity_free (async_context->validity);
+
+       g_free (async_context->userid);
+
+       g_slice_free (AsyncContext, async_context);
+}
+
+static void
 cipher_context_set_session (CamelCipherContext *context,
                             CamelSession *session)
 {
@@ -136,40 +177,40 @@ cipher_context_finalize (GObject *object)
 }
 
 static const gchar *
-cipher_hash_to_id (CamelCipherContext *context,
-                   CamelCipherHash hash)
+cipher_context_hash_to_id (CamelCipherContext *context,
+                           CamelCipherHash hash)
 {
        return NULL;
 }
 
 static CamelCipherHash
-cipher_id_to_hash (CamelCipherContext *context,
-                   const gchar *id)
+cipher_context_id_to_hash (CamelCipherContext *context,
+                           const gchar *id)
 {
        return CAMEL_CIPHER_HASH_DEFAULT;
 }
 
-static gint
-cipher_sign_sync (CamelCipherContext *ctx,
-                  const gchar *userid,
-                  CamelCipherHash hash,
-                  CamelMimePart *ipart,
-                  CamelMimePart *opart,
-                  GCancellable *cancellable,
-                  GError **error)
+static gboolean
+cipher_context_sign_sync (CamelCipherContext *ctx,
+                          const gchar *userid,
+                          CamelCipherHash hash,
+                          CamelMimePart *ipart,
+                          CamelMimePart *opart,
+                          GCancellable *cancellable,
+                          GError **error)
 {
        g_set_error (
                error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                _("Signing is not supported by this cipher"));
 
-       return -1;
+       return FALSE;
 }
 
 static CamelCipherValidity *
-cipher_verify_sync (CamelCipherContext *context,
-                    CamelMimePart *sigpart,
-                    GCancellable *cancellable,
-                    GError **error)
+cipher_context_verify_sync (CamelCipherContext *context,
+                            CamelMimePart *sigpart,
+                            GCancellable *cancellable,
+                            GError **error)
 {
        g_set_error (
                error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
@@ -178,28 +219,28 @@ cipher_verify_sync (CamelCipherContext *context,
        return NULL;
 }
 
-static gint
-cipher_encrypt_sync (CamelCipherContext *context,
-                     const gchar *userid,
-                     GPtrArray *recipients,
-                     CamelMimePart *ipart,
-                     CamelMimePart *opart,
-                     GCancellable *cancellable,
-                     GError **error)
+static gboolean
+cipher_context_encrypt_sync (CamelCipherContext *context,
+                             const gchar *userid,
+                             GPtrArray *recipients,
+                             CamelMimePart *ipart,
+                             CamelMimePart *opart,
+                             GCancellable *cancellable,
+                             GError **error)
 {
        g_set_error (
                error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                _("Encryption is not supported by this cipher"));
 
-       return -1;
+       return FALSE;
 }
 
 static CamelCipherValidity *
-cipher_decrypt_sync (CamelCipherContext *context,
-                     CamelMimePart *ipart,
-                     CamelMimePart *opart,
-                     GCancellable *cancellable,
-                     GError **error)
+cipher_context_decrypt_sync (CamelCipherContext *context,
+                             CamelMimePart *ipart,
+                             CamelMimePart *opart,
+                             GCancellable *cancellable,
+                             GError **error)
 {
        g_set_error (
                error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
@@ -208,31 +249,469 @@ cipher_decrypt_sync (CamelCipherContext *context,
        return NULL;
 }
 
-static gint
-cipher_import_keys_sync (CamelCipherContext *context,
-                         CamelStream *istream,
-                         GCancellable *cancellable,
-                         GError **error)
+static gboolean
+cipher_context_import_keys_sync (CamelCipherContext *context,
+                                 CamelStream *istream,
+                                 GCancellable *cancellable,
+                                 GError **error)
 {
        g_set_error (
                error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                _("You may not import keys with this cipher"));
 
-       return -1;
+       return FALSE;
 }
 
 static gint
-cipher_export_keys_sync (CamelCipherContext *context,
-                         GPtrArray *keys,
-                         CamelStream *ostream,
-                         GCancellable *cancellable,
-                         GError **error)
+cipher_context_export_keys_sync (CamelCipherContext *context,
+                                 GPtrArray *keys,
+                                 CamelStream *ostream,
+                                 GCancellable *cancellable,
+                                 GError **error)
 {
        g_set_error (
                error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                _("You may not export keys with this cipher"));
 
-       return -1;
+       return FALSE;
+}
+
+static void
+cipher_context_sign_thread (GSimpleAsyncResult *simple,
+                            GObject *object,
+                            GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_cipher_context_sign_sync (
+               CAMEL_CIPHER_CONTEXT (object),
+               async_context->userid, async_context->hash,
+               async_context->ipart, async_context->opart,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+cipher_context_sign (CamelCipherContext *context,
+                     const gchar *userid,
+                     CamelCipherHash hash,
+                     CamelMimePart *ipart,
+                     CamelMimePart *opart,
+                     gint io_priority,
+                     GCancellable *cancellable,
+                     GAsyncReadyCallback callback,
+                     gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->userid = g_strdup (userid);
+       async_context->hash = hash;
+       async_context->ipart = g_object_ref (ipart);
+       async_context->opart = g_object_ref (opart);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (context), callback, user_data, cipher_context_sign);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, cipher_context_sign_thread, io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+cipher_context_sign_finish (CamelCipherContext *context,
+                            GAsyncResult *result,
+                            GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (context), cipher_context_sign), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
+cipher_context_verify_thread (GSimpleAsyncResult *simple,
+                              GObject *object,
+                              GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       async_context->validity = camel_cipher_context_verify_sync (
+               CAMEL_CIPHER_CONTEXT (object), async_context->ipart,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+cipher_context_verify (CamelCipherContext *context,
+                       CamelMimePart *ipart,
+                       gint io_priority,
+                       GCancellable *cancellable,
+                       GAsyncReadyCallback callback,
+                       gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->ipart = g_object_ref (ipart);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (context), callback,
+               user_data, cipher_context_verify);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, cipher_context_verify_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static CamelCipherValidity *
+cipher_context_verify_finish (CamelCipherContext *context,
+                              GAsyncResult *result,
+                              GError **error)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+       CamelCipherValidity *validity;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (context), cipher_context_verify), NULL);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
+
+       validity = async_context->validity;
+       async_context->validity = NULL;
+
+       return validity;
+}
+
+static void
+cipher_context_encrypt_thread (GSimpleAsyncResult *simple,
+                               GObject *object,
+                               GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_cipher_context_encrypt_sync (
+               CAMEL_CIPHER_CONTEXT (object),
+               async_context->userid, async_context->strings,
+               async_context->ipart, async_context->opart,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+cipher_context_encrypt (CamelCipherContext *context,
+                        const gchar *userid,
+                        GPtrArray *recipients,
+                        CamelMimePart *ipart,
+                        CamelMimePart *opart,
+                        gint io_priority,
+                        GCancellable *cancellable,
+                        GAsyncReadyCallback callback,
+                        gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+       guint ii;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->userid = g_strdup (userid);
+       async_context->strings = g_ptr_array_new ();
+       async_context->ipart = g_object_ref (ipart);
+       async_context->opart = g_object_ref (opart);
+
+       for (ii = 0; ii < recipients->len; ii++)
+               g_ptr_array_add (
+                       async_context->strings,
+                       g_strdup (recipients->pdata[ii]));
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (context), callback,
+               user_data, cipher_context_encrypt);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, cipher_context_encrypt_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+cipher_context_encrypt_finish (CamelCipherContext *context,
+                               GAsyncResult *result,
+                               GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (context), cipher_context_encrypt), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
+cipher_context_decrypt_thread (GSimpleAsyncResult *simple,
+                               GObject *object,
+                               GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       async_context->validity = camel_cipher_context_decrypt_sync (
+               CAMEL_CIPHER_CONTEXT (object), async_context->ipart,
+               async_context->opart, cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+cipher_context_decrypt (CamelCipherContext *context,
+                        CamelMimePart *ipart,
+                        CamelMimePart *opart,
+                        gint io_priority,
+                        GCancellable *cancellable,
+                        GAsyncReadyCallback callback,
+                        gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->ipart = g_object_ref (ipart);
+       async_context->opart = g_object_ref (opart);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (context), callback,
+               user_data, cipher_context_decrypt);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, cipher_context_decrypt_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static CamelCipherValidity *
+cipher_context_decrypt_finish (CamelCipherContext *context,
+                               GAsyncResult *result,
+                               GError **error)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+       CamelCipherValidity *validity;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (context), cipher_context_decrypt), NULL);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
+
+       validity = async_context->validity;
+       async_context->validity = NULL;
+
+       return validity;
+}
+
+static void
+cipher_context_import_keys_thread (GSimpleAsyncResult *simple,
+                                   GObject *object,
+                                   GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_cipher_context_import_keys_sync (
+               CAMEL_CIPHER_CONTEXT (object), async_context->stream,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+cipher_context_import_keys (CamelCipherContext *context,
+                            CamelStream *istream,
+                            gint io_priority,
+                            GCancellable *cancellable,
+                            GAsyncReadyCallback callback,
+                            gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->stream = g_object_ref (istream);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (context), callback,
+               user_data, cipher_context_import_keys);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, cipher_context_import_keys_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+cipher_context_import_keys_finish (CamelCipherContext *context,
+                                   GAsyncResult *result,
+                                   GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (context),
+               cipher_context_import_keys), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
+cipher_context_export_keys_thread (GSimpleAsyncResult *simple,
+                                   GObject *object,
+                                   GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_cipher_context_export_keys_sync (
+               CAMEL_CIPHER_CONTEXT (object), async_context->strings,
+               async_context->stream, cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+cipher_context_export_keys (CamelCipherContext *context,
+                            GPtrArray *keys,
+                            CamelStream *ostream,
+                            gint io_priority,
+                            GCancellable *cancellable,
+                            GAsyncReadyCallback callback,
+                            gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+       guint ii;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->strings = g_ptr_array_new ();
+       async_context->stream = g_object_ref (ostream);
+
+       for (ii = 0; ii < keys->len; ii++)
+               g_ptr_array_add (
+                       async_context->strings,
+                       g_strdup (keys->pdata[ii]));
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (context), callback,
+               user_data, cipher_context_export_keys);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, cipher_context_export_keys_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+cipher_context_export_keys_finish (CamelCipherContext *context,
+                                   GAsyncResult *result,
+                                   GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (context),
+               cipher_context_export_keys), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
 }
 
 static void
@@ -248,14 +727,28 @@ camel_cipher_context_class_init (CamelCipherContextClass *class)
        object_class->dispose = cipher_context_dispose;
        object_class->finalize = cipher_context_finalize;
 
-       class->hash_to_id = cipher_hash_to_id;
-       class->id_to_hash = cipher_id_to_hash;
-       class->sign_sync = cipher_sign_sync;
-       class->verify_sync = cipher_verify_sync;
-       class->encrypt_sync = cipher_encrypt_sync;
-       class->decrypt_sync = cipher_decrypt_sync;
-       class->import_keys_sync = cipher_import_keys_sync;
-       class->export_keys_sync = cipher_export_keys_sync;
+       class->hash_to_id = cipher_context_hash_to_id;
+       class->id_to_hash = cipher_context_id_to_hash;
+
+       class->sign_sync = cipher_context_sign_sync;
+       class->verify_sync = cipher_context_verify_sync;
+       class->encrypt_sync = cipher_context_encrypt_sync;
+       class->decrypt_sync = cipher_context_decrypt_sync;
+       class->import_keys_sync = cipher_context_import_keys_sync;
+       class->export_keys_sync = cipher_context_export_keys_sync;
+
+       class->sign = cipher_context_sign;
+       class->sign_finish = cipher_context_sign_finish;
+       class->verify = cipher_context_verify;
+       class->verify_finish = cipher_context_verify_finish;
+       class->encrypt = cipher_context_encrypt;
+       class->encrypt_finish = cipher_context_encrypt_finish;
+       class->decrypt = cipher_context_decrypt;
+       class->decrypt_finish = cipher_context_decrypt_finish;
+       class->import_keys = cipher_context_import_keys;
+       class->import_keys_finish = cipher_context_import_keys_finish;
+       class->export_keys = cipher_context_export_keys;
+       class->export_keys_finish = cipher_context_export_keys_finish;
 
        g_object_class_install_property (
                object_class,
@@ -277,81 +770,169 @@ camel_cipher_context_init (CamelCipherContext *context)
 }
 
 /**
- * camel_cipher_sign_sync:
- * @context: Cipher Context
- * @userid: private key to use to sign the stream
+ * camel_cipher_context_sign_sync:
+ * @context: a #CamelCipherContext
+ * @userid: private key to use to sign the stream
  * @hash: preferred Message-Integrity-Check hash algorithm
- * @ipart: Input part.
- * @opart: output part.
+ * @ipart: input #CamelMimePart
+ * @opart: output #CamelMimePart
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
- * Converts the (unsigned) part @ipart into a new self-contained mime
+ * Converts the (unsigned) part @ipart into a new self-contained MIME
  * part @opart.  This may be a multipart/signed part, or a simple part
  * for enveloped types.
  *
- * Returns: 0 for success or -1 for failure.
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
-gint
-camel_cipher_sign_sync (CamelCipherContext *context,
-                        const gchar *userid,
-                        CamelCipherHash hash,
-                        CamelMimePart *ipart,
-                        CamelMimePart *opart,
-                        GCancellable *cancellable,
-                        GError **error)
+gboolean
+camel_cipher_context_sign_sync (CamelCipherContext *context,
+                                const gchar *userid,
+                                CamelCipherHash hash,
+                                CamelMimePart *ipart,
+                                CamelMimePart *opart,
+                                GCancellable *cancellable,
+                                GError **error)
 {
        CamelCipherContextClass *class;
-       gint retval;
+       gboolean success;
 
-       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
+       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
 
        class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
-       g_return_val_if_fail (class->sign_sync != NULL, -1);
+       g_return_val_if_fail (class->sign_sync != NULL, FALSE);
 
        CIPHER_LOCK (context);
 
-       retval = class->sign_sync (
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               CIPHER_UNLOCK (context);
+               return FALSE;
+       }
+
+       camel_operation_push_message (cancellable, _("Signing message"));
+
+       success = class->sign_sync (
                context, userid, hash, ipart, opart, cancellable, error);
-       CAMEL_CHECK_GERROR (context, sign_sync, retval == 0, error);
+       CAMEL_CHECK_GERROR (context, sign_sync, success, error);
+
+       camel_operation_pop_message (cancellable);
 
        CIPHER_UNLOCK (context);
 
-       return retval;
+       return success;
+}
+
+/**
+ * camel_cipher_context_sign:
+ * @context: a #CamelCipherContext
+ * @userid: a private key to use to sign the stream
+ * @hash: preferred Message-Integrity-Check hash algorithm
+ * @ipart: input #CamelMimePart
+ * @opart: output #CamelMimePart
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously converts the (unsigned) part @ipart into a new
+ * self-contained MIME part @opart.  This may be a multipart/signed part,
+ * or a simple part for enveloped types.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_cipher_context_sign_finish() to get the result of the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_cipher_context_sign (CamelCipherContext *context,
+                           const gchar *userid,
+                           CamelCipherHash hash,
+                           CamelMimePart *ipart,
+                           CamelMimePart *opart,
+                           gint io_priority,
+                           GCancellable *cancellable,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
+{
+       CamelCipherContextClass *class;
+
+       g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
+
+       class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
+       g_return_if_fail (class->sign != NULL);
+
+       class->sign (
+               context, userid, hash, ipart, opart, io_priority,
+               cancellable, callback, user_data);
 }
 
 /**
- * camel_cipher_verify_sync:
- * @context: Cipher Context
- * @ipart: part to verify
+ * camel_cipher_context_sign_finish:
+ * @context: a #CamelCipherContext
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_cipher_context_sign().
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_cipher_context_sign_finish (CamelCipherContext *context,
+                                  GAsyncResult *result,
+                                  GError **error)
+{
+       CamelCipherContextClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
+       g_return_val_if_fail (class->sign_finish != NULL, FALSE);
+
+       return class->sign_finish (context, result, error);
+}
+
+/**
+ * camel_cipher_context_verify_sync:
+ * @context: a #CamelCipherContext
+ * @ipart: the #CamelMimePart to verify
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
- * Verifies the signature. If @istream is a clearsigned stream,
- * you should pass %NULL as the sigstream parameter. Otherwise
- * @sigstream is assumed to be the signature stream and is used to
- * verify the integirity of the @istream.
+ * Verifies the signature.
  *
- * Returns: a CamelCipherValidity structure containing information
- * about the integrity of the input stream or %NULL on failure to
- * execute at all.
+ * Returns: a #CamelCipherValidity structure containing information
+ * about the integrity of the input stream, or %NULL on failure to
+ * execute at all
  **/
 CamelCipherValidity *
-camel_cipher_verify_sync (CamelCipherContext *context,
-                          CamelMimePart *ipart,
-                          GCancellable *cancellable,
-                          GError **error)
+camel_cipher_context_verify_sync (CamelCipherContext *context,
+                                  CamelMimePart *ipart,
+                                  GCancellable *cancellable,
+                                  GError **error)
 {
        CamelCipherContextClass *class;
        CamelCipherValidity *valid;
 
        g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
+       g_return_val_if_fail (CAMEL_IS_MIME_PART (ipart), NULL);
 
        class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
        g_return_val_if_fail (class->verify_sync != NULL, NULL);
 
        CIPHER_LOCK (context);
 
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               CIPHER_UNLOCK (context);
+               return NULL;
+       }
+
        valid = class->verify_sync (context, ipart, cancellable, error);
        CAMEL_CHECK_GERROR (context, verify_sync, valid != NULL, error);
 
@@ -361,162 +942,542 @@ camel_cipher_verify_sync (CamelCipherContext *context,
 }
 
 /**
- * camel_cipher_encrypt_sync:
- * @context: Cipher Context
- * @userid: key id (or email address) to use when signing, or NULL to not sign.
- * @recipients: an array of recipient key ids and/or email addresses
- * @ipart: cleartext input stream
- * @opart: ciphertext output stream
+ * camel_cipher_context_verify:
+ * @context: a #CamelCipherContext
+ * @ipart: the #CamelMimePart to verify
+ * @io_priority: the I/O priority of the request
  * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously verifies the signature.
+ *
+ * When the operation is finished, @callback will be called.  You can
+ * then call camel_cipher_context_verify_finish() to get the result of
+ * the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_cipher_context_verify (CamelCipherContext *context,
+                             CamelMimePart *ipart,
+                             gint io_priority,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
+{
+       CamelCipherContextClass *class;
+
+       g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
+       g_return_if_fail (CAMEL_IS_MIME_PART (ipart));
+
+       class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
+       g_return_if_fail (class->verify != NULL);
+
+       class->verify (
+               context, ipart, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_cipher_context_verify_finish:
+ * @context: a #CamelCipherContext
+ * @result: a #GAsyncResult
  * @error: return location for a #GError, or %NULL
  *
- * Encrypts (and optionally signs) the cleartext input stream and
- * writes the resulting ciphertext to the output stream.
+ * Finishes the operation started with camel_cipher_context_verify().
  *
- * Returns: 0 for success or -1 for failure.
+ * Returns: a #CamelCipherValidity structure containing information
+ * about the integrity of the input stream, or %NULL on failure to
+ * execute at all
+ *
+ * Since: 2.34
  **/
-gint
-camel_cipher_encrypt_sync (CamelCipherContext *context,
-                           const gchar *userid,
-                           GPtrArray *recipients,
-                           CamelMimePart *ipart,
-                           CamelMimePart *opart,
-                           GCancellable *cancellable,
-                           GError **error)
+CamelCipherValidity *
+camel_cipher_context_verify_finish (CamelCipherContext *context,
+                                    GAsyncResult *result,
+                                    GError **error)
+{
+       CamelCipherContextClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (context), NULL);
+
+       class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
+       g_return_val_if_fail (class->verify_finish != NULL, NULL);
+
+       return class->verify_finish (context, result, error);
+}
+
+/**
+ * camel_cipher_context_encrypt_sync:
+ * @context: a #CamelCipherContext
+ * @userid: key ID (or email address) to use when signing, or %NULL to not sign
+ * @recipients: an array of recipient key IDs and/or email addresses
+ * @ipart: clear-text #CamelMimePart
+ * @opart: cipher-text #CamelMimePart
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Encrypts (and optionally signs) the clear-text @ipart and writes the
+ * resulting cipher-text to @opart.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_cipher_context_encrypt_sync (CamelCipherContext *context,
+                                   const gchar *userid,
+                                   GPtrArray *recipients,
+                                   CamelMimePart *ipart,
+                                   CamelMimePart *opart,
+                                   GCancellable *cancellable,
+                                   GError **error)
 {
        CamelCipherContextClass *class;
-       gint retval;
+       gboolean success;
 
-       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
+       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
+       g_return_val_if_fail (CAMEL_IS_MIME_PART (ipart), FALSE);
+       g_return_val_if_fail (CAMEL_IS_MIME_PART (opart), FALSE);
 
        class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
-       g_return_val_if_fail (class->encrypt_sync != NULL, -1);
+       g_return_val_if_fail (class->encrypt_sync != NULL, FALSE);
 
        CIPHER_LOCK (context);
 
-       retval = class->encrypt_sync (
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               CIPHER_UNLOCK (context);
+               return FALSE;
+       }
+
+       camel_operation_push_message (cancellable, _("Encrypting message"));
+
+       success = class->encrypt_sync (
                context, userid, recipients,
                ipart, opart, cancellable, error);
-       CAMEL_CHECK_GERROR (context, encrypt_sync, retval == 0, error);
+       CAMEL_CHECK_GERROR (context, encrypt_sync, success, error);
+
+       camel_operation_pop_message (cancellable);
 
        CIPHER_UNLOCK (context);
 
-       return retval;
+       return success;
 }
 
 /**
- * camel_cipher_decrypt_sync:
- * @context:
- * @ipart:
- * @opart:
+ * camel_cipher_context_encrypt:
+ * @context: a #CamelCipherContext
+ * @userid: key id (or email address) to use when signing, or %NULL to not sign
+ * @recipients: an array of recipient key IDs and/or email addresses
+ * @ipart: clear-text #CamelMimePart
+ * @opart: cipher-text #CamelMimePart
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously encrypts (and optionally signs) the clear-text @ipart and
+ * writes the resulting cipher-text to @opart.
+ *
+ * When the operation is finished, @callback will be called.  You can
+ * then call camel_cipher_context_encrypt_finish() to get the result of
+ * the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_cipher_context_encrypt (CamelCipherContext *context,
+                              const gchar *userid,
+                              GPtrArray *recipients,
+                              CamelMimePart *ipart,
+                              CamelMimePart *opart,
+                              gint io_priority,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
+{
+       CamelCipherContextClass *class;
+
+       g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
+       g_return_if_fail (CAMEL_IS_MIME_PART (ipart));
+       g_return_if_fail (CAMEL_IS_MIME_PART (opart));
+
+       class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
+       g_return_if_fail (class->encrypt != NULL);
+
+       class->encrypt (
+               context, userid, recipients, ipart, opart,
+               io_priority, cancellable, callback, user_data);
+}
+
+/**
+ * camel_cipher_context_encrypt_finish:
+ * @context: a #CamelCipherContext
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_cipher_context_encrypt().
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_cipher_context_encrypt_finish (CamelCipherContext *context,
+                                     GAsyncResult *result,
+                                     GError **error)
+{
+       CamelCipherContextClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
+       g_return_val_if_fail (class->encrypt_finish != NULL, FALSE);
+
+       return class->encrypt_finish (context, result, error);
+}
+
+/**
+ * camel_cipher_context_decrypt_sync:
+ * @context: a #CamelCipherContext
+ * @ipart: cipher-text #CamelMimePart
+ * @opart: clear-text #CamelMimePart
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Decrypts @ipart into @opart.
  *
- * Returns: A validity/encryption status.
+ * Returns: a validity/encryption status, or %NULL on error
+ *
+ * Since: 2.34
  **/
 CamelCipherValidity *
-camel_cipher_decrypt_sync (CamelCipherContext *context,
-                           CamelMimePart *ipart,
-                           CamelMimePart *opart,
-                           GCancellable *cancellable,
-                           GError **error)
+camel_cipher_context_decrypt_sync (CamelCipherContext *context,
+                                   CamelMimePart *ipart,
+                                   CamelMimePart *opart,
+                                   GCancellable *cancellable,
+                                   GError **error)
 {
        CamelCipherContextClass *class;
        CamelCipherValidity *valid;
 
        g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
+       g_return_val_if_fail (CAMEL_IS_MIME_PART (ipart), NULL);
+       g_return_val_if_fail (CAMEL_IS_MIME_PART (opart), NULL);
 
        class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
        g_return_val_if_fail (class->decrypt_sync != NULL, NULL);
 
        CIPHER_LOCK (context);
 
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               CIPHER_UNLOCK (context);
+               return NULL;
+       }
+
+       camel_operation_push_message (cancellable, _("Decrypting message"));
+
        valid = class->decrypt_sync (
                context, ipart, opart, cancellable, error);
        CAMEL_CHECK_GERROR (context, decrypt_sync, valid != NULL, error);
 
+       camel_operation_pop_message (cancellable);
+
        CIPHER_UNLOCK (context);
 
        return valid;
 }
 
 /**
- * camel_cipher_import_keys_sync:
- * @context: Cipher Context
- * @istream: input stream (containing keys)
+ * camel_cipher_context_decrypt:
+ * @context: a #CamelCipherContext
+ * @ipart: cipher-text #CamelMimePart
+ * @opart: clear-text #CamelMimePart
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously decrypts @ipart into @opart.
+ *
+ * When the operation is finished, @callback will be called.  You can
+ * then call camel_cipher_context_decrypt_finish() to get the result of
+ * the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_cipher_context_decrypt (CamelCipherContext *context,
+                              CamelMimePart *ipart,
+                              CamelMimePart *opart,
+                              gint io_priority,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
+{
+       CamelCipherContextClass *class;
+
+       g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
+       g_return_if_fail (CAMEL_IS_MIME_PART (ipart));
+       g_return_if_fail (CAMEL_IS_MIME_PART (opart));
+
+       class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
+       g_return_if_fail (class->decrypt != NULL);
+
+       class->decrypt (
+               context, ipart, opart, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_cipher_context_decrypt_finish:
+ * @context: a #CamelCipherContext
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_cipher_context_decrypt().
+ *
+ * Returns: a validity/encryption status, or %NULL on error
+ *
+ * Since: 2.34
+ **/
+CamelCipherValidity *
+camel_cipher_context_decrypt_finish (CamelCipherContext *context,
+                                     GAsyncResult *result,
+                                     GError **error)
+{
+       CamelCipherContextClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+       class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
+       g_return_val_if_fail (class->decrypt_finish != NULL, NULL);
+
+       return class->decrypt_finish (context, result, error);
+}
+
+/**
+ * camel_cipher_context_import_keys_sync:
+ * @context: a #CamelCipherContext
+ * @istream: an input stream containing keys
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Imports a stream of keys/certificates contained within @istream
- * into the key/certificate database controlled by @ctx.
+ * into the key/certificate database controlled by @context.
  *
- * Returns: 0 on success or -1 on fail.
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
-gint
-camel_cipher_import_keys_sync (CamelCipherContext *context,
-                               CamelStream *istream,
-                               GCancellable *cancellable,
-                               GError **error)
+gboolean
+camel_cipher_context_import_keys_sync (CamelCipherContext *context,
+                                       CamelStream *istream,
+                                       GCancellable *cancellable,
+                                       GError **error)
 {
        CamelCipherContextClass *class;
-       gint retval;
+       gboolean success;
 
-       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
-       g_return_val_if_fail (CAMEL_IS_STREAM (istream), -1);
+       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
+       g_return_val_if_fail (CAMEL_IS_STREAM (istream), FALSE);
 
        class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
-       g_return_val_if_fail (class->import_keys_sync != NULL, -1);
+       g_return_val_if_fail (class->import_keys_sync != NULL, FALSE);
 
-       retval = class->import_keys_sync (
+       success = class->import_keys_sync (
                context, istream, cancellable, error);
-       CAMEL_CHECK_GERROR (context, import_keys_sync, retval == 0, error);
+       CAMEL_CHECK_GERROR (context, import_keys_sync, success, error);
+
+       return success;
+}
+
+/**
+ * camel_cipher_context_import_keys:
+ * @context: a #CamelCipherContext
+ * @istream: an input stream containing keys
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously imports a stream of keys/certificates contained within
+ * @istream into the key/certificate database controlled by @context.
+ *
+ * When the operation is finished, @callback will be called.  You can
+ * then call camel_cipher_context_import_keys_finish() to get the result
+ * of the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_cipher_context_import_keys (CamelCipherContext *context,
+                                  CamelStream *istream,
+                                  gint io_priority,
+                                  GCancellable *cancellable,
+                                  GAsyncReadyCallback callback,
+                                  gpointer user_data)
+{
+       CamelCipherContextClass *class;
+
+       g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
+       g_return_if_fail (CAMEL_IS_STREAM (istream));
 
-       return retval;
+       class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
+       g_return_if_fail (class->import_keys != NULL);
+
+       class->import_keys (
+               context, istream, io_priority,
+               cancellable, callback, user_data);
 }
 
 /**
- * camel_cipher_export_keys_sync:
- * @context: Cipher Context
- * @keys: an array of key ids
- * @ostream: output stream
+ * camel_cipher_context_import_keys_finish:
+ * @context: a #CamelCipherContext
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_cipher_context_import_keys().
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_cipher_context_import_keys_finish (CamelCipherContext *context,
+                                         GAsyncResult *result,
+                                         GError **error)
+{
+       CamelCipherContextClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
+       g_return_val_if_fail (class->import_keys_finish != NULL, FALSE);
+
+       return class->import_keys_finish (context, result, error);
+}
+
+/**
+ * camel_cipher_context_export_keys_sync:
+ * @context: a #CamelCipherContext
+ * @keys: an array of key IDs
+ * @ostream: an output stream
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Exports the keys/certificates in @keys to the stream @ostream from
- * the key/certificate database controlled by @ctx.
+ * the key/certificate database controlled by @context.
  *
- * Returns: 0 on success or -1 on fail.
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
-gint
-camel_cipher_export_keys_sync (CamelCipherContext *context,
-                               GPtrArray *keys,
-                               CamelStream *ostream,
-                               GCancellable *cancellable,
-                               GError **error)
+gboolean
+camel_cipher_context_export_keys_sync (CamelCipherContext *context,
+                                       GPtrArray *keys,
+                                       CamelStream *ostream,
+                                       GCancellable *cancellable,
+                                       GError **error)
 {
        CamelCipherContextClass *class;
-       gint retval;
+       gboolean success;
 
-       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), -1);
-       g_return_val_if_fail (CAMEL_IS_STREAM (ostream), -1);
-       g_return_val_if_fail (keys != NULL, -1);
+       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
+       g_return_val_if_fail (keys != NULL, FALSE);
+       g_return_val_if_fail (CAMEL_IS_STREAM (ostream), FALSE);
 
        class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
-       g_return_val_if_fail (class->export_keys_sync != NULL, -1);
+       g_return_val_if_fail (class->export_keys_sync != NULL, FALSE);
 
-       retval = class->export_keys_sync (
+       success = class->export_keys_sync (
                context, keys, ostream, cancellable, error);
-       CAMEL_CHECK_GERROR (context, export_keys_sync, retval == 0, error);
+       CAMEL_CHECK_GERROR (context, export_keys_sync, success, error);
+
+       return success;
+}
+
+/**
+ * camel_cipher_context_export_keys:
+ * @context: a #CamelCipherContext
+ * @keys: an array of key IDs
+ * @ostream: an output stream
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously exports the keys/certificates in @keys to the stream
+ * @ostream from the key/certificate database controlled by @context.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_cipher_context_export_keys_finish() to get the result of the
+ * operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_cipher_context_export_keys (CamelCipherContext *context,
+                                  GPtrArray *keys,
+                                  CamelStream *ostream,
+                                  gint io_priority,
+                                  GCancellable *cancellable,
+                                  GAsyncReadyCallback callback,
+                                  gpointer user_data)
+{
+       CamelCipherContextClass *class;
+
+       g_return_if_fail (CAMEL_IS_CIPHER_CONTEXT (context));
+       g_return_if_fail (keys != NULL);
+       g_return_if_fail (CAMEL_IS_STREAM (ostream));
+
+       class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
+       g_return_if_fail (class->export_keys != NULL);
+
+       class->export_keys (
+               context, keys, ostream, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_cipher_context_export_keys_finish:
+ * @context: a #CamelCipherContext
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_cipher_context_export_keys().
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_cipher_context_export_keys_finish (CamelCipherContext *context,
+                                         GAsyncResult *result,
+                                         GError **error)
+{
+       CamelCipherContextClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_CIPHER_CONTEXT (context), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
+       g_return_val_if_fail (class->export_keys_finish != NULL, FALSE);
 
-       return retval;
+       return class->export_keys_finish (context, result, error);
 }
 
 /* a couple of util functions */
 CamelCipherHash
-camel_cipher_id_to_hash (CamelCipherContext *context,
-                         const gchar *id)
+camel_cipher_context_id_to_hash (CamelCipherContext *context,
+                                 const gchar *id)
 {
        CamelCipherContextClass *class;
 
@@ -532,8 +1493,8 @@ camel_cipher_id_to_hash (CamelCipherContext *context,
 }
 
 const gchar *
-camel_cipher_hash_to_id (CamelCipherContext *context,
-                         CamelCipherHash hash)
+camel_cipher_context_hash_to_id (CamelCipherContext *context,
+                                 CamelCipherHash hash)
 {
        CamelCipherContextClass *class;
 
index e3d231a..71da9d6 100644 (file)
@@ -134,12 +134,14 @@ struct _CamelCipherContextClass {
        const gchar *encrypt_protocol;
        const gchar *key_protocol;
 
+       /* Non-Blocking Methods */
        CamelCipherHash (*id_to_hash)           (CamelCipherContext *context,
                                                 const gchar *id);
        const gchar *   (*hash_to_id)           (CamelCipherContext *context,
                                                 CamelCipherHash hash);
 
-       gint            (*sign_sync)            (CamelCipherContext *context,
+       /* Synchronous I/O Methods */
+       gboolean        (*sign_sync)            (CamelCipherContext *context,
                                                 const gchar *userid,
                                                 CamelCipherHash hash,
                                                 CamelMimePart *ipart,
@@ -151,7 +153,7 @@ struct _CamelCipherContextClass {
                                                 CamelMimePart *ipart,
                                                 GCancellable *cancellable,
                                                 GError **error);
-       gint            (*encrypt_sync)         (CamelCipherContext *context,
+       gboolean        (*encrypt_sync)         (CamelCipherContext *context,
                                                 const gchar *userid,
                                                 GPtrArray *recipients,
                                                 CamelMimePart *ipart,
@@ -164,26 +166,93 @@ struct _CamelCipherContextClass {
                                                 CamelMimePart *opart,
                                                 GCancellable *cancellable,
                                                 GError **error);
-       gint            (*import_keys_sync)     (CamelCipherContext *context,
+       gboolean        (*import_keys_sync)     (CamelCipherContext *context,
                                                 CamelStream *istream,
                                                 GCancellable *cancellable,
                                                 GError **error);
-       gint            (*export_keys_sync)     (CamelCipherContext *context,
+       gboolean        (*export_keys_sync)     (CamelCipherContext *context,
                                                 GPtrArray *keys,
                                                 CamelStream *ostream,
                                                 GCancellable *cancellable,
                                                 GError **error);
+
+       /* Asynchronous I/O Methods (all have defaults) */
+       void            (*sign)                 (CamelCipherContext *context,
+                                                const gchar *userid,
+                                                CamelCipherHash hash,
+                                                CamelMimePart *ipart,
+                                                CamelMimePart *opart,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*sign_finish)          (CamelCipherContext *context,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*verify)               (CamelCipherContext *context,
+                                                CamelMimePart *ipart,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       CamelCipherValidity *
+                       (*verify_finish)        (CamelCipherContext *context,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*encrypt)              (CamelCipherContext *context,
+                                                const gchar *user_id,
+                                                GPtrArray *recipients,
+                                                CamelMimePart *ipart,
+                                                CamelMimePart *opart,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*encrypt_finish)       (CamelCipherContext *context,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*decrypt)              (CamelCipherContext *context,
+                                                CamelMimePart *ipart,
+                                                CamelMimePart *opart,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       CamelCipherValidity *
+                       (*decrypt_finish)       (CamelCipherContext *context,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*import_keys)          (CamelCipherContext *context,
+                                                CamelStream *istream,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*import_keys_finish)   (CamelCipherContext *context,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*export_keys)          (CamelCipherContext *context,
+                                                GPtrArray *keys,
+                                                CamelStream *ostream,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*export_keys_finish)   (CamelCipherContext *context,
+                                                GAsyncResult *result,
+                                                GError **error);
 };
 
 GType          camel_cipher_context_get_type   (void);
 CamelCipherContext *
                camel_cipher_context_new        (CamelSession *session);
-CamelSession * camel_cipher_context_get_session (CamelCipherContext *context);
+CamelSession * camel_cipher_context_get_session
+                                               (CamelCipherContext *context);
 
 /* cipher context util routines */
-CamelCipherHash        camel_cipher_id_to_hash         (CamelCipherContext *context,
+CamelCipherHash        camel_cipher_context_id_to_hash (CamelCipherContext *context,
                                                 const gchar *id);
-const gchar *  camel_cipher_hash_to_id         (CamelCipherContext *context,
+const gchar *  camel_cipher_context_hash_to_id (CamelCipherContext *context,
                                                 CamelCipherHash hash);
 
 /* FIXME:
@@ -192,41 +261,118 @@ const gchar *    camel_cipher_hash_to_id         (CamelCipherContext *context,
    to the cipher, etc etc. */
 
 /* cipher routines */
-gint           camel_cipher_sign_sync          (CamelCipherContext *context,
+gboolean       camel_cipher_context_sign_sync  (CamelCipherContext *context,
                                                 const gchar *userid,
                                                 CamelCipherHash hash,
                                                 CamelMimePart *ipart,
                                                 CamelMimePart *opart,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_cipher_context_sign       (CamelCipherContext *context,
+                                                const gchar *userid,
+                                                CamelCipherHash hash,
+                                                CamelMimePart *ipart,
+                                                CamelMimePart *opart,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_cipher_context_sign_finish
+                                               (CamelCipherContext *context,
+                                                GAsyncResult *result,
+                                                GError **error);
+CamelCipherValidity *
+               camel_cipher_context_verify_sync
+                                               (CamelCipherContext *context,
+                                                CamelMimePart *ipart,
+                                                GCancellable *cancellable,
+                                                GError **error);
+void           camel_cipher_context_verify     (CamelCipherContext *context,
+                                                CamelMimePart *ipart,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
 CamelCipherValidity *
-               camel_cipher_verify_sync        (CamelCipherContext *context,
+               camel_cipher_context_verify_finish
+                                               (CamelCipherContext *context,
+                                                GAsyncResult *result,
+                                                GError **error);
+gboolean       camel_cipher_context_encrypt_sync
+                                               (CamelCipherContext *context,
+                                                const gchar *userid,
+                                                GPtrArray *recipients,
                                                 CamelMimePart *ipart,
+                                                CamelMimePart *opart,
                                                 GCancellable *cancellable,
                                                 GError **error);
-gint           camel_cipher_encrypt_sync       (CamelCipherContext *context,
+void           camel_cipher_context_encrypt    (CamelCipherContext *context,
                                                 const gchar *userid,
                                                 GPtrArray *recipients,
                                                 CamelMimePart *ipart,
                                                 CamelMimePart *opart,
+                                                gint io_priority,
                                                 GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_cipher_context_encrypt_finish
+                                               (CamelCipherContext *context,
+                                                GAsyncResult *result,
                                                 GError **error);
 CamelCipherValidity *
-               camel_cipher_decrypt_sync       (CamelCipherContext *context,
+               camel_cipher_context_decrypt_sync
+                                               (CamelCipherContext *context,
                                                 CamelMimePart *ipart,
                                                 CamelMimePart *opart,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_cipher_context_decrypt    (CamelCipherContext *context,
+                                                CamelMimePart *ipart,
+                                                CamelMimePart *opart,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+CamelCipherValidity *
+               camel_cipher_context_decrypt_finish
+                                               (CamelCipherContext *context,
+                                                GAsyncResult *result,
+                                                GError **error);
 
 /* key/certificate routines */
-gint           camel_cipher_import_keys_sync   (CamelCipherContext *context,
+gboolean       camel_cipher_context_import_keys_sync
+                                               (CamelCipherContext *context,
                                                 CamelStream *istream,
                                                 GCancellable *cancellable,
                                                 GError **error);
-gint           camel_cipher_export_keys_sync   (CamelCipherContext *context,
+void           camel_cipher_context_import_keys
+                                               (CamelCipherContext *context,
+                                                CamelStream *istream,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_cipher_context_import_keys_finish
+                                               (CamelCipherContext *context,
+                                                GAsyncResult *result,
+                                                GError **error);
+gboolean       camel_cipher_context_export_keys_sync
+                                               (CamelCipherContext *context,
+                                                GPtrArray *keys,
+                                                CamelStream *ostream,
+                                                GCancellable *cancellable,
+                                                GError **error);
+void           camel_cipher_context_export_keys
+                                               (CamelCipherContext *context,
                                                 GPtrArray *keys,
                                                 CamelStream *ostream,
+                                                gint io_priority,
                                                 GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_cipher_context_export_keys_finish
+                                               (CamelCipherContext *context,
+                                                GAsyncResult *result,
                                                 GError **error);
 
 /* CamelCipherValidity utility functions */
index 4969f78..a9f9a0b 100644 (file)
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), CAMEL_TYPE_DATA_WRAPPER, CamelDataWrapperPrivate))
 
+typedef struct _AsyncContext AsyncContext;
+
 struct _CamelDataWrapperPrivate {
        GStaticMutex stream_lock;
 };
 
+struct _AsyncContext {
+       /* arguments */
+       CamelStream *stream;
+
+       /* results */
+       gssize bytes_written;
+};
+
+static void
+async_context_free (AsyncContext *async_context)
+{
+       if (async_context->stream != NULL)
+               g_object_unref (async_context->stream);
+
+       g_slice_free (AsyncContext, async_context);
+}
+
 G_DEFINE_TYPE (CamelDataWrapper, camel_data_wrapper, CAMEL_TYPE_OBJECT)
 
 static void
@@ -130,8 +149,17 @@ data_wrapper_write_to_stream_sync (CamelDataWrapper *data_wrapper,
        }
 
        camel_data_wrapper_lock (data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK);
+
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_data_wrapper_unlock (
+                       data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK);
+               return -1;
+       }
+
        if (camel_stream_reset (data_wrapper->stream, error) == -1) {
-               camel_data_wrapper_unlock (data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK);
+               camel_data_wrapper_unlock (
+                       data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK);
                return -1;
        }
 
@@ -191,7 +219,7 @@ data_wrapper_decode_to_stream_sync (CamelDataWrapper *data_wrapper,
        return ret;
 }
 
-static gint
+static gboolean
 data_wrapper_construct_from_stream_sync (CamelDataWrapper *data_wrapper,
                                          CamelStream *stream,
                                          GCancellable *cancellable,
@@ -202,7 +230,217 @@ data_wrapper_construct_from_stream_sync (CamelDataWrapper *data_wrapper,
 
        data_wrapper->stream = g_object_ref (stream);
 
-       return 0;
+       return TRUE;
+}
+
+static void
+data_wrapper_write_to_stream_thread (GSimpleAsyncResult *simple,
+                                     GObject *object,
+                                     GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       async_context->bytes_written =
+               camel_data_wrapper_write_to_stream_sync (
+                       CAMEL_DATA_WRAPPER (object),
+                       async_context->stream,
+                       cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper,
+                              CamelStream *stream,
+                              gint io_priority,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->stream = g_object_ref (stream);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (data_wrapper), callback,
+               user_data, data_wrapper_write_to_stream);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, data_wrapper_write_to_stream_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gssize
+data_wrapper_write_to_stream_finish (CamelDataWrapper *data_wrapper,
+                                     GAsyncResult *result,
+                                     GError **error)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (data_wrapper),
+               data_wrapper_write_to_stream), -1);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       if (g_simple_async_result_propagate_error (simple, error))
+               return -1;
+
+       return async_context->bytes_written;
+}
+
+static void
+data_wrapper_decode_to_stream_thread (GSimpleAsyncResult *simple,
+                                      GObject *object,
+                                      GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       async_context->bytes_written =
+               camel_data_wrapper_decode_to_stream_sync (
+                       CAMEL_DATA_WRAPPER (object),
+                       async_context->stream,
+                       cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+data_wrapper_decode_to_stream (CamelDataWrapper *data_wrapper,
+                               CamelStream *stream,
+                               gint io_priority,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->stream = g_object_ref (stream);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (data_wrapper), callback,
+               user_data, data_wrapper_decode_to_stream);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, data_wrapper_decode_to_stream_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gssize
+data_wrapper_decode_to_stream_finish (CamelDataWrapper *data_wrapper,
+                                      GAsyncResult *result,
+                                      GError **error)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (data_wrapper),
+               data_wrapper_decode_to_stream), -1);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       if (g_simple_async_result_propagate_error (simple, error))
+               return -1;
+
+       return async_context->bytes_written;
+}
+
+static void
+data_wrapper_construct_from_stream_thread (GSimpleAsyncResult *simple,
+                                           GObject *object,
+                                           GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_data_wrapper_construct_from_stream_sync (
+               CAMEL_DATA_WRAPPER (object), async_context->stream,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+data_wrapper_construct_from_stream (CamelDataWrapper *data_wrapper,
+                                    CamelStream *stream,
+                                    gint io_priority,
+                                    GCancellable *cancellable,
+                                    GAsyncReadyCallback callback,
+                                    gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->stream = g_object_ref (stream);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (data_wrapper), callback, user_data,
+               data_wrapper_construct_from_stream);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, data_wrapper_construct_from_stream_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+data_wrapper_construct_from_stream_finish (CamelDataWrapper *data_wrapper,
+                                           GAsyncResult *result,
+                                           GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (data_wrapper),
+               data_wrapper_construct_from_stream), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
 }
 
 static void
@@ -221,9 +459,17 @@ camel_data_wrapper_class_init (CamelDataWrapperClass *class)
        class->get_mime_type_field = data_wrapper_get_mime_type_field;
        class->set_mime_type_field = data_wrapper_set_mime_type_field;
        class->is_offline = data_wrapper_is_offline;
+
        class->write_to_stream_sync = data_wrapper_write_to_stream_sync;
        class->decode_to_stream_sync = data_wrapper_decode_to_stream_sync;
        class->construct_from_stream_sync = data_wrapper_construct_from_stream_sync;
+
+       class->write_to_stream = data_wrapper_write_to_stream;
+       class->write_to_stream_finish = data_wrapper_write_to_stream_finish;
+       class->decode_to_stream = data_wrapper_decode_to_stream;
+       class->decode_to_stream_finish = data_wrapper_decode_to_stream_finish;
+       class->construct_from_stream = data_wrapper_construct_from_stream;
+       class->construct_from_stream_finish = data_wrapper_construct_from_stream_finish;
 }
 
 static void
@@ -254,7 +500,7 @@ camel_data_wrapper_new (void)
 
 /**
  * camel_data_wrapper_set_mime_type:
- * @data_wrapper: a #CamelDataWrapper object
+ * @data_wrapper: a #CamelDataWrapper
  * @mime_type: a MIME type
  *
  * This sets the data wrapper's MIME type.
@@ -282,7 +528,7 @@ camel_data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper,
 
 /**
  * camel_data_wrapper_get_mime_type:
- * @data_wrapper: a #CamelDataWrapper object
+ * @data_wrapper: a #CamelDataWrapper
  *
  * Returns: the MIME type which must be freed by the caller
  **/
@@ -301,7 +547,7 @@ camel_data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper)
 
 /**
  * camel_data_wrapper_get_mime_type_field:
- * @data_wrapper: a #CamelDataWrapper object
+ * @data_wrapper: a #CamelDataWrapper
  *
  * Returns: the parsed form of the data wrapper's MIME type
  **/
@@ -320,7 +566,7 @@ camel_data_wrapper_get_mime_type_field (CamelDataWrapper *data_wrapper)
 
 /**
  * camel_data_wrapper_set_mime_type_field:
- * @data_wrapper: a #CamelDataWrapper object
+ * @data_wrapper: a #CamelDataWrapper
  * @mime_type: a #CamelContentType
  *
  * This sets the data wrapper's MIME type. It suffers from the same
@@ -343,7 +589,7 @@ camel_data_wrapper_set_mime_type_field (CamelDataWrapper *data_wrapper,
 
 /**
  * camel_data_wrapper_is_offline:
- * @data_wrapper: a #CamelDataWrapper object
+ * @data_wrapper: a #CamelDataWrapper
  *
  * Returns: whether @data_wrapper is "offline" (data stored
  * remotely) or not. Some optional code paths may choose to not
@@ -363,18 +609,77 @@ camel_data_wrapper_is_offline (CamelDataWrapper *data_wrapper)
 }
 
 /**
+ * camel_data_wrapper_lock:
+ * @data_wrapper: a #CamelDataWrapper
+ * @lock: lock type to lock
+ *
+ * Locks #data_wrapper's #lock. Unlock it with camel_data_wrapper_unlock().
+ *
+ * Since: 2.32
+ **/
+void
+camel_data_wrapper_lock (CamelDataWrapper *data_wrapper,
+                         CamelDataWrapperLock lock)
+{
+       g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
+
+       switch (lock) {
+       case CAMEL_DATA_WRAPPER_STREAM_LOCK:
+               g_static_mutex_lock (&data_wrapper->priv->stream_lock);
+               break;
+       default:
+               g_return_if_reached ();
+       }
+}
+
+/**
+ * camel_data_wrapper_unlock:
+ * @data_wrapper: a #CamelDataWrapper
+ * @lock: lock type to unlock
+ *
+ * Unlocks #data_wrapper's #lock, previously locked with
+ * camel_data_wrapper_lock().
+ *
+ * Since: 2.32
+ **/
+void
+camel_data_wrapper_unlock (CamelDataWrapper *data_wrapper,
+                           CamelDataWrapperLock lock)
+{
+       g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
+
+       switch (lock) {
+       case CAMEL_DATA_WRAPPER_STREAM_LOCK:
+               g_static_mutex_unlock (&data_wrapper->priv->stream_lock);
+               break;
+       default:
+               g_return_if_reached ();
+       }
+}
+
+/**
  * camel_data_wrapper_write_to_stream_sync:
- * @data_wrapper: a #CamelDataWrapper object
+ * @data_wrapper: a #CamelDataWrapper
  * @stream: a #CamelStream for output
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Writes the content of @data_wrapper to @stream in a machine-independent
- * format appropriate for the data. It should be possible to construct an
+ * format appropriate for the data.  It should be possible to construct an
  * equivalent data wrapper object later by passing this stream to
- * #camel_data_wrapper_construct_from_stream.
+ * camel_data_wrapper_construct_from_stream_sync().
+ *
+ * <note>
+ *   <para>
+ *     This function may block even if the given output stream does not.
+ *     For example, the content may have to be fetched across a network
+ *     before it can be written to @stream.
+ *   </para>
+ * </note>
  *
- * Returns: the number of bytes written, or %-1 on fail
+ * Returns: the number of bytes written, or %-1 on error
+ *
+ * Since: 2.34
  **/
 gssize
 camel_data_wrapper_write_to_stream_sync (CamelDataWrapper *data_wrapper,
@@ -400,15 +705,94 @@ camel_data_wrapper_write_to_stream_sync (CamelDataWrapper *data_wrapper,
 }
 
 /**
+ * camel_data_wrapper_write_to_stream:
+ * @data_wrapper: a #CamelDataWrapper
+ * @stream: a #CamelStream for writed data to be written to
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously writes the content of @data_wrapper to @stream in a
+ * machine-independent format appropriate for the data.  It should be
+ * possible to construct an equivalent data wrapper object later by
+ * passing this stream to camel_data_wrapper_construct_from_stream().
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_data_wrapper_write_to_stream_finish() to get the result of
+ * the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_data_wrapper_write_to_stream (CamelDataWrapper *data_wrapper,
+                                    CamelStream *stream,
+                                    gint io_priority,
+                                    GCancellable *cancellable,
+                                    GAsyncReadyCallback callback,
+                                    gpointer user_data)
+{
+       CamelDataWrapperClass *class;
+
+       g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
+       g_return_if_fail (CAMEL_IS_STREAM (stream));
+
+       class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
+       g_return_if_fail (class->write_to_stream != NULL);
+
+       class->write_to_stream (
+               data_wrapper, stream, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_data_wrapper_write_to_stream_finish:
+ * @data_wrapper: a #CamelDataWrapper
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_data_wrapper_write_to_stream().
+ *
+ * Returns: the number of bytes written, or %-1 or error
+ *
+ * Since: 2.34
+ **/
+gssize
+camel_data_wrapper_write_to_stream_finish (CamelDataWrapper *data_wrapper,
+                                           GAsyncResult *result,
+                                           GError **error)
+{
+       CamelDataWrapperClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
+
+       class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
+       g_return_val_if_fail (class->write_to_stream_finish != NULL, -1);
+
+       return class->write_to_stream_finish (data_wrapper, result, error);
+}
+
+/**
  * camel_data_wrapper_decode_to_stream_sync:
- * @data_wrapper: a #CamelDataWrapper object
+ * @data_wrapper: a #CamelDataWrapper
  * @stream: a #CamelStream for decoded data to be written to
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Writes the decoded data content to @stream.
  *
- * Returns: the number of bytes written, or %-1 on fail
+ * <note>
+ *   <para>
+ *     This function may block even if the given output stream does not.
+ *     For example, the content may have to be fetched across a network
+ *     before it can be written to @stream.
+ *   </para>
+ * </note>
+ *
+ * Returns: the number of bytes written, or %-1 on error
+ *
+ * Since: 2.34
  **/
 gssize
 camel_data_wrapper_decode_to_stream_sync (CamelDataWrapper *data_wrapper,
@@ -434,24 +818,92 @@ camel_data_wrapper_decode_to_stream_sync (CamelDataWrapper *data_wrapper,
 }
 
 /**
+ * camel_data_wrapper_decode_to_stream:
+ * @data_wrapper: a #CamelDataWrapper
+ * @stream: a #CamelStream for decoded data to be written to
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously writes the decoded data content to @stream.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_data_wrapper_decode_to_stream_finish() to get the result of
+ * the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_data_wrapper_decode_to_stream (CamelDataWrapper *data_wrapper,
+                                     CamelStream *stream,
+                                     gint io_priority,
+                                     GCancellable *cancellable,
+                                     GAsyncReadyCallback callback,
+                                     gpointer user_data)
+{
+       CamelDataWrapperClass *class;
+
+       g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
+       g_return_if_fail (CAMEL_IS_STREAM (stream));
+
+       class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
+       g_return_if_fail (class->decode_to_stream != NULL);
+
+       class->decode_to_stream (
+               data_wrapper, stream, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_data_wrapper_decode_to_stream_finish:
+ * @data_wrapper: a #CamelDataWrapper
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_data_wrapper_decode_to_stream().
+ *
+ * Returns: the number of bytes written, or %-1 on error
+ *
+ * Since: 2.34
+ **/
+gssize
+camel_data_wrapper_decode_to_stream_finish (CamelDataWrapper *data_wrapper,
+                                            GAsyncResult *result,
+                                            GError **error)
+{
+       CamelDataWrapperClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
+
+       class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
+       g_return_val_if_fail (class->decode_to_stream_finish != NULL, -1);
+
+       return class->decode_to_stream_finish (data_wrapper, result, error);
+}
+
+/**
  * camel_data_wrapper_construct_from_stream_sync:
- * @data_wrapper: a #CamelDataWrapper object
+ * @data_wrapper: a #CamelDataWrapper
  * @stream: an input #CamelStream
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
- * Constructs the content of @data_wrapper from the supplied @stream.
+ * Constructs the content of @data_wrapper from the given @stream.
+ *
+ * Returns: %TRUE on success, %FALSE on error
  *
- * Returns: %0 on success or %-1 on fail
+ * Since: 2.34
  **/
-gint
+gboolean
 camel_data_wrapper_construct_from_stream_sync (CamelDataWrapper *data_wrapper,
                                                CamelStream *stream,
                                                GCancellable *cancellable,
                                                GError **error)
 {
        CamelDataWrapperClass *class;
-       gint retval;
+       gboolean success;
 
        g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), -1);
        g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1);
@@ -459,59 +911,78 @@ camel_data_wrapper_construct_from_stream_sync (CamelDataWrapper *data_wrapper,
        class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
        g_return_val_if_fail (class->construct_from_stream_sync != NULL, -1);
 
-       retval = class->construct_from_stream_sync (
+       success = class->construct_from_stream_sync (
                data_wrapper, stream, cancellable, error);
        CAMEL_CHECK_GERROR (
-               data_wrapper, construct_from_stream_sync, retval == 0, error);
+               data_wrapper, construct_from_stream_sync, success, error);
 
-       return retval;
+       return success;
 }
 
 /**
- * camel_data_wrapper_lock:
+ * camel_data_wrapper_construct_from_stream:
  * @data_wrapper: a #CamelDataWrapper
- * @lock: lock type to lock
+ * @stream: an input #CamelStream
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
  *
- * Locks #data_wrapper's #lock. Unlock it with camel_data_wrapper_unlock().
+ * Asynchronously constructs the content of @data_wrapper from the given
+ * @stream.
  *
- * Since: 2.32
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_data_wrapper_construct_from_stream_finish() to get the result
+ * of the operation.
+ *
+ * Since: 2.34
  **/
 void
-camel_data_wrapper_lock (CamelDataWrapper *data_wrapper,
-                         CamelDataWrapperLock lock)
+camel_data_wrapper_construct_from_stream (CamelDataWrapper *data_wrapper,
+                                          CamelStream *stream,
+                                          gint io_priority,
+                                          GCancellable *cancellable,
+                                          GAsyncReadyCallback callback,
+                                          gpointer user_data)
 {
+       CamelDataWrapperClass *class;
+
        g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
+       g_return_if_fail (CAMEL_IS_STREAM (stream));
 
-       switch (lock) {
-       case CAMEL_DATA_WRAPPER_STREAM_LOCK:
-               g_static_mutex_lock (&data_wrapper->priv->stream_lock);
-               break;
-       default:
-               g_return_if_reached ();
-       }
+       class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
+       g_return_if_fail (class->construct_from_stream != NULL);
+
+       class->construct_from_stream (
+               data_wrapper, stream, io_priority,
+               cancellable, callback, user_data);
 }
 
 /**
- * camel_data_wrapper_unlock:
+ * camel_data_wrapper_construct_from_stream_finish:
  * @data_wrapper: a #CamelDataWrapper
- * @lock: lock type to unlock
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
  *
- * Unlocks #data_wrapper's #lock, previously locked with
- * camel_data_wrapper_lock().
+ * Finishes the operation started with
+ * camel_data_wrapper_construct_from_stream().
  *
- * Since: 2.32
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
-void
-camel_data_wrapper_unlock (CamelDataWrapper *data_wrapper,
-                           CamelDataWrapperLock lock)
+gboolean
+camel_data_wrapper_construct_from_stream_finish (CamelDataWrapper *data_wrapper,
+                                                 GAsyncResult *result,
+                                                 GError **error)
 {
-       g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper));
+       CamelDataWrapperClass *class;
 
-       switch (lock) {
-       case CAMEL_DATA_WRAPPER_STREAM_LOCK:
-               g_static_mutex_unlock (&data_wrapper->priv->stream_lock);
-               break;
-       default:
-               g_return_if_reached ();
-       }
+       g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_DATA_WRAPPER_GET_CLASS (data_wrapper);
+       g_return_val_if_fail (class->construct_from_stream_finish != NULL, FALSE);
+
+       return class->construct_from_stream_finish (data_wrapper, result, error);
 }
index adde135..d363456 100644 (file)
@@ -83,6 +83,7 @@ struct _CamelDataWrapper {
 struct _CamelDataWrapperClass {
        CamelObjectClass parent_class;
 
+       /* Non-Blocking Methods */
        void            (*set_mime_type)        (CamelDataWrapper *data_wrapper,
                                                 const gchar *mime_type);
        gchar *         (*get_mime_type)        (CamelDataWrapper *data_wrapper);
@@ -92,6 +93,7 @@ struct _CamelDataWrapperClass {
                                                 CamelContentType *mime_type_field);
        gboolean        (*is_offline)           (CamelDataWrapper *data_wrapper);
 
+       /* Synchronous I/O Methods */
        gssize          (*write_to_stream_sync) (CamelDataWrapper *data_wrapper,
                                                 CamelStream *stream,
                                                 GCancellable *cancellable,
@@ -100,11 +102,44 @@ struct _CamelDataWrapperClass {
                                                 CamelStream *stream,
                                                 GCancellable *cancellable,
                                                 GError **error);
-       gint            (*construct_from_stream_sync)
+       gboolean        (*construct_from_stream_sync)
                                                (CamelDataWrapper *data_wrapper,
                                                 CamelStream *stream,
                                                 GCancellable *cancellable,
                                                 GError **error);
+
+       /* Asyncrhonous I/O Methods (all have defaults) */
+       void            (*write_to_stream)      (CamelDataWrapper *data_wrapper,
+                                                CamelStream *stream,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gssize          (*write_to_stream_finish)
+                                               (CamelDataWrapper *data_wrapper,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*decode_to_stream)     (CamelDataWrapper *data_wrapper,
+                                                CamelStream *stream,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gssize          (*decode_to_stream_finish)
+                                               (CamelDataWrapper *data_wrapper,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*construct_from_stream)
+                                               (CamelDataWrapper *data_wrapper,
+                                                CamelStream *stream,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*construct_from_stream_finish)
+                                               (CamelDataWrapper *data_wrapper,
+                                                GAsyncResult *result,
+                                                GError **error);
 };
 
 GType          camel_data_wrapper_get_type     (void);
@@ -120,25 +155,59 @@ void              camel_data_wrapper_set_mime_type_field
                                                (CamelDataWrapper *data_wrapper,
                                                 CamelContentType *mime_type);
 gboolean       camel_data_wrapper_is_offline   (CamelDataWrapper *data_wrapper);
+void           camel_data_wrapper_lock         (CamelDataWrapper *data_wrapper,
+                                                CamelDataWrapperLock lock);
+void           camel_data_wrapper_unlock       (CamelDataWrapper *data_wrapper,
+                                                CamelDataWrapperLock lock);
+
 gssize         camel_data_wrapper_write_to_stream_sync
                                                (CamelDataWrapper *data_wrapper,
                                                 CamelStream *stream,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_data_wrapper_write_to_stream
+                                               (CamelDataWrapper *data_wrapper,
+                                                CamelStream *stream,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gssize         camel_data_wrapper_write_to_stream_finish
+                                               (CamelDataWrapper *data_wrapper,
+                                                GAsyncResult *result,
+                                                GError **error);
 gssize         camel_data_wrapper_decode_to_stream_sync
                                                (CamelDataWrapper *data_wrapper,
                                                 CamelStream *stream,
                                                 GCancellable *cancellable,
                                                 GError **error);
-gint           camel_data_wrapper_construct_from_stream_sync
+void           camel_data_wrapper_decode_to_stream
                                                (CamelDataWrapper *data_wrapper,
                                                 CamelStream *stream,
+                                                gint io_priority,
                                                 GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gssize         camel_data_wrapper_decode_to_stream_finish
+                                               (CamelDataWrapper *data_wrapper,
+                                                GAsyncResult *result,
+                                                GError **error);
+gboolean       camel_data_wrapper_construct_from_stream_sync
+                                               (CamelDataWrapper *data_wrapper,
+                                                CamelStream *stream,
+                                                GCancellable *cancellable,
+                                                GError **error);
+void           camel_data_wrapper_construct_from_stream
+                                               (CamelDataWrapper *data_wrapper,
+                                                CamelStream *stream,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_data_wrapper_construct_from_stream_finish
+                                               (CamelDataWrapper *data_wrapper,
+                                                GAsyncResult *result,
                                                 GError **error);
-void           camel_data_wrapper_lock         (CamelDataWrapper *data_wrapper,
-                                                CamelDataWrapperLock lock);
-void           camel_data_wrapper_unlock       (CamelDataWrapper *data_wrapper,
-                                                CamelDataWrapperLock lock);
 
 G_END_DECLS
 
index a2d7148..bf047ff 100644 (file)
@@ -47,7 +47,7 @@ typedef struct _CamelDBPrivate CamelDBPrivate;
  *
  * Since: 2.24
  **/
-typedef gint (*CamelDBCollate)(gpointer ,int,gconstpointer ,int,gconstpointer );
+typedef gint (*CamelDBCollate)(gpointer, gint, gconstpointer, gint, gconstpointer );
 
 /**
  * CamelDB:
index 530d386..9c48a6a 100644 (file)
@@ -300,7 +300,8 @@ camel_disco_diary_replay (CamelDiscoDiary *diary,
        g_return_if_fail (size != 0);
        rewind (diary->file);
 
-       camel_operation_start (cancellable, _("Resynchronizing with server"));
+       camel_operation_push_message (
+               cancellable, _("Resynchronizing with server"));
 
        while (local_error == NULL) {
                camel_operation_progress (
@@ -390,8 +391,8 @@ camel_disco_diary_replay (CamelDiscoDiary *diary,
                        }
 
                        camel_folder_transfer_messages_to_sync (
-                               source, uids, destination, &ret_uids,
-                               delete_originals, cancellable, &local_error);
+                               source, uids, destination, delete_originals,
+                               &ret_uids, cancellable, &local_error);
 
                        if (ret_uids) {
                                for (i = 0; i < uids->len; i++) {
@@ -410,7 +411,7 @@ camel_disco_diary_replay (CamelDiscoDiary *diary,
        }
 
  lose:
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        /* Close folders */
        g_hash_table_foreach (
index 6fd9009..65e1031 100644 (file)
@@ -62,7 +62,7 @@ cdf_sync_offline (CamelSession *session, CamelSessionThreadMsg *mm)
        struct _cdf_sync_msg *m = (struct _cdf_sync_msg *)mm;
        gint i;
 
-       camel_operation_start (
+       camel_operation_push_message (
                mm->cancellable,
                _("Downloading new messages for offline mode"));
 
@@ -81,7 +81,7 @@ cdf_sync_offline (CamelSession *session, CamelSessionThreadMsg *mm)
                                                       NULL, &mm->error);
        }
 
-       camel_operation_end (mm->cancellable);
+       camel_operation_pop_message (mm->cancellable);
 }
 
 static void
@@ -203,7 +203,7 @@ disco_expunge_uids (CamelFolder *folder,
 static gboolean
 disco_append_message_sync (CamelFolder *folder,
                            CamelMimeMessage *message,
-                           const CamelMessageInfo *info,
+                           CamelMessageInfo *info,
                            gchar **appended_uid,
                            GCancellable *cancellable,
                            GError **error)
@@ -336,8 +336,8 @@ static gboolean
 disco_transfer_messages_to_sync (CamelFolder *source,
                                  GPtrArray *uids,
                                  CamelFolder *dest,
-                                 GPtrArray **transferred_uids,
                                  gboolean delete_originals,
+                                 GPtrArray **transferred_uids,
                                  GCancellable *cancellable,
                                  GError **error)
 {
@@ -385,7 +385,7 @@ disco_prepare_for_offline (CamelDiscoFolder *disco_folder,
        gint i;
        gboolean success = TRUE;
 
-       camel_operation_start (
+       camel_operation_push_message (
                cancellable, _("Preparing folder '%s' for offline"),
                camel_folder_get_full_name (folder));
 
@@ -395,7 +395,7 @@ disco_prepare_for_offline (CamelDiscoFolder *disco_folder,
                uids = camel_folder_get_uids (folder);
 
        if (!uids) {
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                return FALSE;
        }
 
@@ -411,7 +411,7 @@ disco_prepare_for_offline (CamelDiscoFolder *disco_folder,
        else
                camel_folder_free_uids (folder, uids);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return success;
 }
index 9a4a77c..2c876cd 100644 (file)
@@ -506,8 +506,8 @@ do_copy (struct _ESExp *f, gint argc, struct _ESExpResult **argv, CamelFilterDri
                                g_ptr_array_add (uids, (gchar *) p->uid);
                                /* FIXME Pass a GCancellable */
                                camel_folder_transfer_messages_to_sync (
-                                       p->source, uids, outbox, NULL,
-                                       FALSE, NULL, &p->error);
+                                       p->source, uids, outbox, FALSE,
+                                       NULL, NULL, &p->error);
                                g_ptr_array_free (uids, TRUE);
                        } else {
                                if (p->message == NULL)
@@ -567,8 +567,8 @@ do_move (struct _ESExp *f, gint argc, struct _ESExpResult **argv, CamelFilterDri
                                g_ptr_array_add (uids, (gchar *) p->uid);
                                /* FIXME Pass a GCancellable */
                                camel_folder_transfer_messages_to_sync (
-                                       p->source, uids, outbox, NULL,
-                                       last, NULL, &p->error);
+                                       p->source, uids, outbox, last,
+                                       NULL, NULL, &p->error);
                                g_ptr_array_free (uids, TRUE);
                        } else {
                                if (p->message == NULL)
@@ -877,8 +877,8 @@ pipe_to_system (struct _ESExp *f, gint argc, struct _ESExpResult **argv, CamelFi
        g_object_unref (mem);
 
        message = camel_mime_message_new ();
-       if (camel_mime_part_construct_from_parser_sync (
-               (CamelMimePart *) message, parser, NULL, NULL) == -1) {
+       if (!camel_mime_part_construct_from_parser_sync (
+               (CamelMimePart *) message, parser, NULL, NULL)) {
                gint err = camel_mime_parser_errno (parser);
                g_set_error (
                        &p->error, G_IO_ERROR,
@@ -1309,8 +1309,8 @@ camel_filter_driver_filter_mbox (CamelFilterDriver *driver,
                message = camel_mime_message_new ();
                mime_part = CAMEL_MIME_PART (message);
 
-               if (camel_mime_part_construct_from_parser_sync (
-                       mime_part, mp, cancellable, error) == -1) {
+               if (!camel_mime_part_construct_from_parser_sync (
+                       mime_part, mp, cancellable, error)) {
                        report_status (driver, CAMEL_FILTER_STATUS_END, 100, _("Failed on message %d"), i);
                        g_object_unref (message);
                        goto fail;
@@ -1672,7 +1672,7 @@ camel_filter_driver_filter_message (CamelFilterDriver *driver,
                        g_ptr_array_add (uids, (gchar *) p->uid);
                        camel_folder_transfer_messages_to_sync (
                                p->source, uids, p->defaultfolder,
-                               NULL, FALSE, cancellable, &p->error);
+                               FALSE, NULL, cancellable, &p->error);
                        g_ptr_array_free (uids, TRUE);
                } else {
                        if (p->message == NULL) {
index 399980e..05c1351 100644 (file)
@@ -1432,7 +1432,8 @@ match_words_1message (CamelDataWrapper *object, struct _camel_search_words *word
                byte_array = g_byte_array_new ();
                stream = camel_stream_mem_new_with_byte_array (byte_array);
 
-               /* FIXME: The match should be part of a stream op */
+               /* FIXME The match should be part of a stream op */
+               /* FIXME Pass a GCancellable and GError here. */
                camel_data_wrapper_decode_to_stream_sync (
                        containee, stream, NULL, NULL);
                camel_stream_write (stream, "", 1, NULL, NULL);
index 489d1c0..1382fd5 100644 (file)
@@ -4043,6 +4043,7 @@ summary_build_content_info_message (CamelFolderSummary *s, CamelMessageInfo *msg
                        CAMEL_STREAM_FILTER (p->filter_stream),
                        p->filter_index);
 
+               /* FIXME Pass a GCancellable and GError here. */
                camel_data_wrapper_decode_to_stream_sync (
                        containee, p->filter_stream, NULL, NULL);
                camel_stream_flush (p->filter_stream, NULL, NULL);
@@ -4452,7 +4453,7 @@ camel_message_info_new (CamelFolderSummary *s)
  *
  * Reference an info.
  **/
-void
+gpointer
 camel_message_info_ref (gpointer o)
 {
        CamelMessageInfo *mi = o;
@@ -4468,6 +4469,8 @@ camel_message_info_ref (gpointer o)
                mi->refcount++;
                GLOBAL_INFO_UNLOCK (info);
        }
+
+       return o;
 }
 
 /**
index 5dcd835..c4e565f 100644 (file)
@@ -435,7 +435,7 @@ void                camel_tag_list_free (CamelTag **list);
 /* Summary may be null */
 /* Use anonymous pointers to avoid tons of cast crap */
 gpointer camel_message_info_new (CamelFolderSummary *summary);
-void camel_message_info_ref (gpointer info);
+gpointer camel_message_info_ref (gpointer info);
 CamelMessageInfo *camel_message_info_new_from_header (CamelFolderSummary *summary, struct _camel_header_raw *header);
 void camel_message_info_free (gpointer info);
 gpointer camel_message_info_clone (gconstpointer info);
index 2863942..66cda68 100644 (file)
@@ -49,6 +49,8 @@
 #define d(x)
 #define w(x)
 
+typedef struct _AsyncContext AsyncContext;
+
 struct _CamelFolderPrivate {
        GStaticRecMutex lock;
        GStaticMutex change_lock;
@@ -64,6 +66,20 @@ struct _CamelFolderPrivate {
        gchar *description;
 };
 
+struct _AsyncContext {
+       /* arguments */
+       CamelMimeMessage *message;  /* also a result */
+       CamelMessageInfo *info;
+       CamelFolder *destination;
+       GPtrArray *message_uids;
+       gchar *message_uid;         /* also a result */
+       gboolean delete_originals;
+       gboolean expunge;
+
+       /* results */
+       GPtrArray *transferred_uids;
+};
+
 struct _CamelFolderChangeInfoPrivate {
        GHashTable *uid_stored; /* what we have stored, which array they're in */
        GHashTable *uid_source; /* used to create unique lists */
@@ -102,6 +118,37 @@ static guint signals[LAST_SIGNAL];
 G_DEFINE_ABSTRACT_TYPE (CamelFolder, camel_folder, CAMEL_TYPE_OBJECT)
 
 static void
+async_context_free (AsyncContext *async_context)
+{
+       if (async_context->message != NULL)
+               g_object_unref (async_context->message);
+
+       /* XXX This is actually an unref.  Good god, no wonder we
+        *     have so many crashes involving CamelMessageInfos! */
+       if (async_context->info != NULL)
+               camel_message_info_free (async_context->info);
+
+       if (async_context->destination != NULL)
+               g_object_unref (async_context->destination);
+
+       if (async_context->message_uids != NULL) {
+               g_ptr_array_foreach (
+                       async_context->message_uids, (GFunc) g_free, NULL);
+               g_ptr_array_free (async_context->message_uids, TRUE);
+       }
+
+       if (async_context->transferred_uids != NULL) {
+               g_ptr_array_foreach (
+                       async_context->transferred_uids, (GFunc) g_free, NULL);
+               g_ptr_array_free (async_context->transferred_uids, TRUE);
+       }
+
+       g_free (async_context->message_uid);
+
+       g_slice_free (AsyncContext, async_context);
+}
+
+static void
 filter_filter (CamelSession *session,
                CamelSessionThreadMsg *tmsg)
 {
@@ -121,7 +168,7 @@ filter_filter (CamelSession *session,
 
        if (m->junk) {
                /* Translators: The %s is replaced with a folder name where the operation is running. */
-               camel_operation_start (
+               camel_operation_push_message (
                        tmsg->cancellable, ngettext (
                        "Learning new spam message in '%s'",
                        "Learning new spam messages in '%s'",
@@ -140,12 +187,12 @@ filter_filter (CamelSession *session,
                                g_object_unref (msg);
                        }
                }
-               camel_operation_end (tmsg->cancellable);
+               camel_operation_pop_message (tmsg->cancellable);
        }
 
        if (m->notjunk) {
                /* Translators: The %s is replaced with a folder name where the operation is running. */
-               camel_operation_start (
+               camel_operation_push_message (
                        tmsg->cancellable, ngettext (
                        "Learning new ham message in '%s'",
                        "Learning new ham messages in '%s'",
@@ -163,7 +210,7 @@ filter_filter (CamelSession *session,
                                g_object_unref (msg);
                        }
                }
-               camel_operation_end (tmsg->cancellable);
+               camel_operation_pop_message (tmsg->cancellable);
        }
 
        if (m->junk || m->notjunk)
@@ -171,7 +218,7 @@ filter_filter (CamelSession *session,
 
        if (m->driver && m->recents) {
                /* Translators: The %s is replaced with a folder name where the operation is running. */
-               camel_operation_start (
+               camel_operation_push_message (
                        tmsg->cancellable, ngettext (
                        "Filtering new message in '%s'",
                        "Filtering new messages in '%s'",
@@ -218,7 +265,7 @@ filter_filter (CamelSession *session,
 
                g_free (source_url);
 
-               camel_operation_end (tmsg->cancellable);
+               camel_operation_pop_message (tmsg->cancellable);
        }
 }
 
@@ -755,8 +802,8 @@ static gboolean
 folder_transfer_messages_to_sync (CamelFolder *source,
                                   GPtrArray *uids,
                                   CamelFolder *dest,
-                                  GPtrArray **transferred_uids,
                                   gboolean delete_originals,
+                                  GPtrArray **transferred_uids,
                                   GCancellable *cancellable,
                                   GError **error)
 {
@@ -770,10 +817,10 @@ folder_transfer_messages_to_sync (CamelFolder *source,
        }
 
        if (delete_originals)
-               camel_operation_start (
+               camel_operation_push_message (
                        cancellable, _("Moving messages"));
        else
-               camel_operation_start (
+               camel_operation_push_message (
                        cancellable, _("Copying messages"));
 
        if (uids->len > 1) {
@@ -798,7 +845,7 @@ folder_transfer_messages_to_sync (CamelFolder *source,
                        camel_folder_thaw (source);
        }
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        if (local_error != NULL)
                g_propagate_error (error, local_error);
@@ -806,6 +853,465 @@ folder_transfer_messages_to_sync (CamelFolder *source,
        return TRUE;
 }
 
+static void
+folder_append_message_thread (GSimpleAsyncResult *simple,
+                              GObject *object,
+                              GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_folder_append_message_sync (
+               CAMEL_FOLDER (object), async_context->message,
+               async_context->info, &async_context->message_uid,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+folder_append_message (CamelFolder *folder,
+                       CamelMimeMessage *message,
+                       CamelMessageInfo *info,
+                       gint io_priority,
+                       GCancellable *cancellable,
+                       GAsyncReadyCallback callback,
+                       gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->message = g_object_ref (message);
+       async_context->info = camel_message_info_ref (info);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (folder), callback,
+               user_data, folder_append_message);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, folder_append_message_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+folder_append_message_finish (CamelFolder *folder,
+                              GAsyncResult *result,
+                              gchar **appended_uid,
+                              GError **error)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (folder), folder_append_message), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       if (appended_uid != NULL) {
+               *appended_uid = async_context->message_uid;
+               async_context->message_uid = NULL;
+       }
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
+folder_expunge_thread (GSimpleAsyncResult *simple,
+                       GObject *object,
+                       GCancellable *cancellable)
+{
+       GError *error = NULL;
+
+       camel_folder_expunge_sync (
+               CAMEL_FOLDER (object), cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+folder_expunge (CamelFolder *folder,
+                gint io_priority,
+                GCancellable *cancellable,
+                GAsyncReadyCallback callback,
+                gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (folder), callback, user_data, folder_expunge);
+
+       g_simple_async_result_run_in_thread (
+               simple, folder_expunge_thread, io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+folder_expunge_finish (CamelFolder *folder,
+                       GAsyncResult *result,
+                       GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (folder), folder_expunge), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
+folder_get_message_thread (GSimpleAsyncResult *simple,
+                           GObject *object,
+                           GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       async_context->message = camel_folder_get_message_sync (
+               CAMEL_FOLDER (object), async_context->message_uid,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+folder_get_message (CamelFolder *folder,
+                    const gchar *message_uid,
+                    gint io_priority,
+                    GCancellable *cancellable,
+                    GAsyncReadyCallback callback,
+                    gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->message_uid = g_strdup (message_uid);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (folder), callback, user_data, folder_get_message);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, folder_get_message_thread, io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static CamelMimeMessage *
+folder_get_message_finish (CamelFolder *folder,
+                           GAsyncResult *result,
+                           GError **error)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (folder), folder_get_message), NULL);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
+
+       return g_object_ref (async_context->message);
+}
+
+static void
+folder_refresh_info_thread (GSimpleAsyncResult *simple,
+                            GObject *object,
+                            GCancellable *cancellable)
+{
+       GError *error = NULL;
+
+       camel_folder_refresh_info_sync (
+               CAMEL_FOLDER (object), cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+folder_refresh_info (CamelFolder *folder,
+                     gint io_priority,
+                     GCancellable *cancellable,
+                     GAsyncReadyCallback callback,
+                     gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (folder), callback, user_data, folder_refresh_info);
+
+       g_simple_async_result_run_in_thread (
+               simple, folder_refresh_info_thread, io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+folder_refresh_info_finish (CamelFolder *folder,
+                            GAsyncResult *result,
+                            GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (folder), folder_refresh_info), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
+folder_synchronize_thread (GSimpleAsyncResult *simple,
+                           GObject *object,
+                           GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_folder_synchronize_sync (
+               CAMEL_FOLDER (object), async_context->expunge,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+folder_synchronize (CamelFolder *folder,
+                    gboolean expunge,
+                    gint io_priority,
+                    GCancellable *cancellable,
+                    GAsyncReadyCallback callback,
+                    gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->expunge = expunge;
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (folder), callback, user_data, folder_synchronize);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, folder_synchronize_thread, io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+folder_synchronize_finish (CamelFolder *folder,
+                           GAsyncResult *result,
+                           GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (folder), folder_synchronize), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
+folder_synchronize_message_thread (GSimpleAsyncResult *simple,
+                                   GObject *object,
+                                   GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_folder_synchronize_message_sync (
+               CAMEL_FOLDER (object), async_context->message_uid,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+folder_synchronize_message (CamelFolder *folder,
+                            const gchar *message_uid,
+                            gint io_priority,
+                            GCancellable *cancellable,
+                            GAsyncReadyCallback callback,
+                            gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->message_uid = g_strdup (message_uid);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (folder), callback,
+               user_data, folder_synchronize_message);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, folder_synchronize_message_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+folder_synchronize_message_finish (CamelFolder *folder,
+                                   GAsyncResult *result,
+                                   GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (folder),
+               folder_synchronize_message), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
+folder_transfer_messages_to_thread (GSimpleAsyncResult *simple,
+                                    GObject *object,
+                                    GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_folder_transfer_messages_to_sync (
+               CAMEL_FOLDER (object), async_context->message_uids,
+               async_context->destination, async_context->delete_originals,
+               &async_context->transferred_uids, cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+folder_transfer_messages_to (CamelFolder *source,
+                             GPtrArray *message_uids,
+                             CamelFolder *destination,
+                             gboolean delete_originals,
+                             gint io_priority,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+       guint ii;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->message_uids = g_ptr_array_new ();
+       async_context->destination = g_object_ref (destination);
+       async_context->delete_originals = delete_originals;
+
+       for (ii = 0; ii < message_uids->len; ii++)
+               g_ptr_array_add (
+                       async_context->message_uids,
+                       g_strdup (message_uids->pdata[ii]));
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (source), callback,
+               user_data, folder_transfer_messages_to);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, folder_transfer_messages_to_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+folder_transfer_messages_to_finish (CamelFolder *source,
+                                    GAsyncResult *result,
+                                    GPtrArray **transferred_uids,
+                                    GError **error)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (source),
+               folder_transfer_messages_to), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       if (transferred_uids != NULL) {
+               *transferred_uids = async_context->transferred_uids;
+               async_context->transferred_uids = NULL;
+       }
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
+
 /* Signal callback that stops emission when folder is frozen. */
 static void
 folder_changed (CamelFolder *folder,
@@ -936,6 +1442,21 @@ camel_folder_class_init (CamelFolderClass *class)
        class->transfer_messages_to_sync = folder_transfer_messages_to_sync;
        class->changed = folder_changed;
 
+       class->append_message = folder_append_message;
+       class->append_message_finish = folder_append_message_finish;
+       class->expunge = folder_expunge;
+       class->expunge_finish = folder_expunge_finish;
+       class->get_message = folder_get_message;
+       class->get_message_finish = folder_get_message_finish;
+       class->refresh_info = folder_refresh_info;
+       class->refresh_info_finish = folder_refresh_info_finish;
+       class->synchronize = folder_synchronize;
+       class->synchronize_finish = folder_synchronize_finish;
+       class->synchronize_message = folder_synchronize_message;
+       class->synchronize_message_finish = folder_synchronize_message_finish;
+       class->transfer_messages_to = folder_transfer_messages_to;
+       class->transfer_messages_to_finish = folder_transfer_messages_to_finish;
+
        /**
         * CamelFolder:description
         *
@@ -1112,114 +1633,42 @@ camel_folder_get_filename (CamelFolder *folder,
 }
 
 /**
- * camel_folder_synchronize_sync:
+ * camel_folder_get_name:
  * @folder: a #CamelFolder
- * @expunge: whether or not to expunge deleted messages
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
  *
- * Sync changes made to a folder to its backing store, possibly
- * expunging deleted messages as well.
+ * Returns the short name of the folder.  The fully qualified name
+ * can be obtained with camel_folder_get_full_name().
  *
- * Returns: %TRUE on success, %FALSE on failure
+ * Returns: the short name of the folder
  **/
-gboolean
-camel_folder_synchronize_sync (CamelFolder *folder,
-                               gboolean expunge,
-                               GCancellable *cancellable,
-                               GError **error)
+const gchar *
+camel_folder_get_name (CamelFolder *folder)
 {
-       CamelFolderClass *class;
-       gboolean success = TRUE;
-
-       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
-
-       class = CAMEL_FOLDER_GET_CLASS (folder);
-       g_return_val_if_fail (class->synchronize_sync != NULL, FALSE);
-
-       camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
-
-       if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED)) {
-               success = class->synchronize_sync (
-                       folder, expunge, cancellable, error);
-               CAMEL_CHECK_GERROR (folder, synchronize_sync, success, error);
-       }
-
-       camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
 
-       return success;
+       return folder->priv->name;
 }
 
 /**
- * camel_folder_refresh_info_sync:
+ * camel_folder_set_name:
  * @folder: a #CamelFolder
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
+ * @name: a name for the folder
  *
- * Updates a folder's summary to be in sync with its backing store.
+ * Sets the short name of the folder.
  *
- * Returns: %TRUE on success, %FALSE on failure
+ * Since: 2.32
  **/
-gboolean
-camel_folder_refresh_info_sync (CamelFolder *folder,
-                                GCancellable *cancellable,
-                                GError **error)
+void
+camel_folder_set_name (CamelFolder *folder,
+                       const gchar *name)
 {
-       CamelFolderClass *class;
-       gboolean success;
-
-       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+       g_return_if_fail (CAMEL_IS_FOLDER (folder));
 
-       class = CAMEL_FOLDER_GET_CLASS (folder);
-       g_return_val_if_fail (class->refresh_info_sync != NULL, FALSE);
+       g_free (folder->priv->name);
+       folder->priv->name = g_strdup (name);
 
-       camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
-
-       success = class->refresh_info_sync (folder, cancellable, error);
-       CAMEL_CHECK_GERROR (folder, refresh_info_sync, success, error);
-
-       camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
-
-       return success;
-}
-
-/**
- * camel_folder_get_name:
- * @folder: a #CamelFolder
- *
- * Returns the short name of the folder.  The fully qualified name
- * can be obtained with camel_folder_get_full_name().
- *
- * Returns: the short name of the folder
- **/
-const gchar *
-camel_folder_get_name (CamelFolder *folder)
-{
-       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
-
-       return folder->priv->name;
-}
-
-/**
- * camel_folder_set_name:
- * @folder: a #CamelFolder
- * @name: a name for the folder
- *
- * Sets the short name of the folder.
- *
- * Since: 2.32
- **/
-void
-camel_folder_set_name (CamelFolder *folder,
-                       const gchar *name)
-{
-       g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
-       g_free (folder->priv->name);
-       folder->priv->name = g_strdup (name);
-
-       g_object_notify (G_OBJECT (folder), "name");
-}
+       g_object_notify (G_OBJECT (folder), "name");
+}
 
 /**
  * camel_folder_get_full_name:
@@ -1316,41 +1765,6 @@ camel_folder_get_parent_store (CamelFolder *folder)
 }
 
 /**
- * camel_folder_expunge_sync:
- * @folder: a #CamelFolder
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Delete messages which have been marked as "DELETED"
- *
- * Returns: %TRUE on success, %FALSE on failure
- **/
-gboolean
-camel_folder_expunge_sync (CamelFolder *folder,
-                           GCancellable *cancellable,
-                           GError **error)
-{
-       CamelFolderClass *class;
-       gboolean success = TRUE;
-
-       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
-
-       class = CAMEL_FOLDER_GET_CLASS (folder);
-       g_return_val_if_fail (class->expunge_sync != NULL, FALSE);
-
-       camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
-
-       if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED)) {
-               success = class->expunge_sync (folder, cancellable, error);
-               CAMEL_CHECK_GERROR (folder, expunge_sync, success, error);
-       }
-
-       camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
-
-       return success;
-}
-
-/**
  * camel_folder_get_message_count:
  * @folder: a #CamelFolder
  *
@@ -1404,50 +1818,6 @@ camel_folder_get_deleted_message_count (CamelFolder *folder)
 }
 
 /**
- * camel_folder_append_message_sync:
- * @folder: a #CamelFolder
- * @message: a #CamelMimeMessage object
- * @info: a #CamelMessageInfo with additional flags/etc to set on
- * new message, or %NULL
- * @appended_uid: if non-%NULL, the UID of the appended message will
- * be returned here, if it is known.
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Append @message to @folder. Only the flag and tag data from @info
- * are used. If @info is %NULL, no flags or tags will be set.
- *
- * Returns: %TRUE on success, %FALSE on failure
- **/
-gboolean
-camel_folder_append_message_sync (CamelFolder *folder,
-                                  CamelMimeMessage *message,
-                                  const CamelMessageInfo *info,
-                                  gchar **appended_uid,
-                                  GCancellable *cancellable,
-                                  GError **error)
-{
-       CamelFolderClass *class;
-       gboolean success;
-
-       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
-       g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
-
-       class = CAMEL_FOLDER_GET_CLASS (folder);
-       g_return_val_if_fail (class->append_message_sync != NULL, FALSE);
-
-       camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
-
-       success = class->append_message_sync (
-               folder, message, info, appended_uid, cancellable, error);
-       CAMEL_CHECK_GERROR (folder, append_message_sync, success, error);
-
-       camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
-
-       return success;
-}
-
-/**
  * camel_folder_get_permanent_flags:
  * @folder: a #CamelFolder
  *
@@ -1750,110 +2120,6 @@ camel_folder_has_summary_capability (CamelFolder *folder)
 /* UIDs stuff */
 
 /**
- * camel_folder_get_message_sync:
- * @folder: a #CamelFolder
- * @uid: the UID
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Get a message from its UID in the folder.
- *
- * Returns: a #CamelMimeMessage corresponding to @uid
- **/
-CamelMimeMessage *
-camel_folder_get_message_sync (CamelFolder *folder,
-                               const gchar *uid,
-                               GCancellable *cancellable,
-                               GError **error)
-{
-       CamelFolderClass *class;
-       CamelMimeMessage *ret;
-
-       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
-       g_return_val_if_fail (uid != NULL, NULL);
-
-       class = CAMEL_FOLDER_GET_CLASS (folder);
-       g_return_val_if_fail (class->get_message_sync != NULL, NULL);
-
-       camel_operation_start (
-               cancellable, _("Retrieving message '%s'"), uid);
-
-       camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
-
-       ret = class->get_message_sync (folder, uid, cancellable, error);
-       CAMEL_CHECK_GERROR (folder, get_message_sync, ret != NULL, error);
-
-       camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
-
-       camel_operation_end (cancellable);
-
-       if (ret && camel_debug_start (":folder")) {
-               printf ("CamelFolder:get_message ('%s', '%s') =\n",
-                       camel_folder_get_full_name (folder), uid);
-               camel_mime_message_dump (ret, FALSE);
-               camel_debug_end ();
-       }
-
-       return ret;
-}
-
-/**
- * camel_folder_synchronize_message_sync:
- * @folder: a #CamelFolder
- * @uid: the UID
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Ensure that a message identified by UID has been synced in the folder (so
- * that camel_folder_get_message on it later will work in offline mode).
- *
- * Returns: %TRUE on success, %FALSE on failure
- *
- * Since: 2.26
- **/
-gboolean
-camel_folder_synchronize_message_sync (CamelFolder *folder,
-                                       const gchar *uid,
-                                       GCancellable *cancellable,
-                                       GError **error)
-{
-       CamelFolderClass *class;
-       gboolean success = FALSE;
-
-       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
-       g_return_val_if_fail (uid != NULL, FALSE);
-
-       class = CAMEL_FOLDER_GET_CLASS (folder);
-       g_return_val_if_fail (class->get_message_sync != NULL, FALSE);
-
-       camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
-
-       /* Use the sync_message method if the class implements it. */
-       if (class->synchronize_message_sync != NULL) {
-               success = class->synchronize_message_sync (
-                       folder, uid, cancellable, error);
-               CAMEL_CHECK_GERROR (
-                       folder, synchronize_message_sync, success, error);
-       } else {
-               CamelMimeMessage *message;
-
-               message = class->get_message_sync (
-                       folder, uid, cancellable, error);
-               CAMEL_CHECK_GERROR (
-                       folder, get_message_sync, message != NULL, error);
-
-               if (message != NULL) {
-                       g_object_unref (message);
-                       success = TRUE;
-               }
-       }
-
-       camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
-
-       return success;
-}
-
-/**
  * camel_folder_get_uids:
  * @folder: a #CamelFolder
  *
@@ -2171,62 +2437,6 @@ camel_folder_search_free (CamelFolder *folder,
 }
 
 /**
- * camel_folder_transfer_messages_to_sync:
- * @source: the source #CamelFolder object
- * @uids: message UIDs in @source
- * @dest: the destination #CamelFolder object
- * @transferred_uids: if non-%NULL, the UIDs of the resulting messages
- * in @dest will be stored here, if known.
- * @delete_originals: whether or not to delete the original messages
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * This copies or moves messages from one folder to another. If the
- * @source and @dest folders have the same parent_store, this may be
- * more efficient than using #camel_folder_append_message.
- *
- * Returns: %TRUE on success, %FALSE on failure
- **/
-gboolean
-camel_folder_transfer_messages_to_sync (CamelFolder *source,
-                                        GPtrArray *uids,
-                                        CamelFolder *dest,
-                                        GPtrArray **transferred_uids,
-                                        gboolean delete_originals,
-                                        GCancellable *cancellable,
-                                        GError **error)
-{
-       CamelFolderClass *class;
-       gboolean success;
-
-       g_return_val_if_fail (CAMEL_IS_FOLDER (source), FALSE);
-       g_return_val_if_fail (CAMEL_IS_FOLDER (dest), FALSE);
-       g_return_val_if_fail (uids != NULL, FALSE);
-
-       if (source == dest || uids->len == 0) {
-               /* source and destination folders are the same, or no work to do, do nothing. */
-               return TRUE;
-       }
-
-       if (source->priv->parent_store == dest->priv->parent_store) {
-               /* If either folder is a vtrash, we need to use the
-                * vtrash transfer method. */
-               if (CAMEL_IS_VTRASH_FOLDER (dest))
-                       class = CAMEL_FOLDER_GET_CLASS (dest);
-               else
-                       class = CAMEL_FOLDER_GET_CLASS (source);
-               success = class->transfer_messages_to_sync (
-                       source, uids, dest, transferred_uids,
-                       delete_originals, cancellable, error);
-       } else
-               success = folder_transfer_messages_to_sync (
-                       source, uids, dest, transferred_uids,
-                       delete_originals, cancellable, error);
-
-       return success;
-}
-
-/**
  * camel_folder_delete:
  * @folder: a #CamelFolder
  *
@@ -2551,19 +2761,843 @@ camel_folder_free_deep (CamelFolder *folder,
 }
 
 /**
- * camel_folder_change_info_new:
- *
- * Create a new folder change info structure.
+ * camel_folder_lock:
+ * @folder: a #CamelFolder
+ * @lock: lock type to lock
  *
- * Change info structures are not MT-SAFE and must be
- * locked for exclusive access externally.
+ * Locks #folder's #lock. Unlock it with camel_folder_unlock().
  *
- * Returns: a new #CamelFolderChangeInfo
+ * Since: 2.32
  **/
-CamelFolderChangeInfo *
-camel_folder_change_info_new (void)
+void
+camel_folder_lock (CamelFolder *folder,
+                   CamelFolderLock lock)
 {
-       CamelFolderChangeInfo *info;
+       g_return_if_fail (CAMEL_IS_FOLDER (folder));
+
+       switch (lock) {
+               case CAMEL_FOLDER_CHANGE_LOCK:
+                       g_static_mutex_lock (&folder->priv->change_lock);
+                       break;
+               case CAMEL_FOLDER_REC_LOCK:
+                       if (folder->priv->skip_folder_lock == FALSE)
+                               g_static_rec_mutex_lock (&folder->priv->lock);
+                       break;
+               default:
+                       g_return_if_reached ();
+       }
+}
+
+/**
+ * camel_folder_unlock:
+ * @folder: a #CamelFolder
+ * @lock: lock type to unlock
+ *
+ * Unlocks #folder's #lock, previously locked with camel_folder_lock().
+ *
+ * Since: 2.32
+ **/
+void
+camel_folder_unlock (CamelFolder *folder,
+                     CamelFolderLock lock)
+{
+       g_return_if_fail (CAMEL_IS_FOLDER (folder));
+
+       switch (lock) {
+               case CAMEL_FOLDER_CHANGE_LOCK:
+                       g_static_mutex_unlock (&folder->priv->change_lock);
+                       break;
+               case CAMEL_FOLDER_REC_LOCK:
+                       if (folder->priv->skip_folder_lock == FALSE)
+                               g_static_rec_mutex_unlock (&folder->priv->lock);
+                       break;
+               default:
+                       g_return_if_reached ();
+       }
+}
+
+/**
+ * camel_folder_append_message_sync:
+ * @folder: a #CamelFolder
+ * @message: a #CamelMimeMessage
+ * @info: a #CamelMessageInfo with additional flags/etc to set on the
+ *        new message, or %NULL
+ * @appended_uid: if non-%NULL, the UID of the appended message will
+ *                be returned here, if it is known
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Appends @message to @folder.  Only the flag and tag data from @info
+ * are used.  If @info is %NULL, no flags or tags will be set.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_folder_append_message_sync (CamelFolder *folder,
+                                  CamelMimeMessage *message,
+                                  CamelMessageInfo *info,
+                                  gchar **appended_uid,
+                                  GCancellable *cancellable,
+                                  GError **error)
+{
+       CamelFolderClass *class;
+       gboolean success;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+       g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), FALSE);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_val_if_fail (class->append_message_sync != NULL, FALSE);
+
+       camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
+
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+               return FALSE;
+       }
+
+       success = class->append_message_sync (
+               folder, message, info, appended_uid, cancellable, error);
+       CAMEL_CHECK_GERROR (folder, append_message_sync, success, error);
+
+       camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+
+       return success;
+}
+
+/**
+ * camel_folder_append_message:
+ * @folder a #CamelFolder
+ * @message: a #CamelMimeMessage
+ * @info: a #CamelMessageInfo with additional flags/etc to set on the
+ *        new message, or %NULL
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Appends @message to @folder asynchronously.  Only the flag and tag data
+ * from @info are used.  If @info is %NULL, no flags or tags will be set.
+ *
+ * When the operation is finished, @callback will be called.  You can
+ * then call camel_folder_append_message_finish() to get the result of
+ * the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_folder_append_message (CamelFolder *folder,
+                             CamelMimeMessage *message,
+                             CamelMessageInfo *info,
+                             gint io_priority,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
+{
+       CamelFolderClass *class;
+
+       g_return_if_fail (CAMEL_IS_FOLDER (folder));
+       g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_if_fail (class->append_message != NULL);
+
+       class->append_message (
+               folder, message, info, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_folder_append_message_finish:
+ * @folder: a #CamelFolder
+ * @result: a #GAsyncResult
+ * @appended_uid: if non-%NULL, the UID of the appended message will
+ *                be returned here, if it is known
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_folder_append_message_finish().
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_folder_append_message_finish (CamelFolder *folder,
+                                    GAsyncResult *result,
+                                    gchar **appended_uid,
+                                    GError **error)
+{
+       CamelFolderClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_val_if_fail (class->append_message_finish != NULL, FALSE);
+
+       return class->append_message_finish (
+               folder, result, appended_uid, error);
+}
+
+/**
+ * camel_folder_expunge_sync:
+ * @folder: a #CamelFolder
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Deletes messages which have been marked as "DELETED".
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_folder_expunge_sync (CamelFolder *folder,
+                           GCancellable *cancellable,
+                           GError **error)
+{
+       CamelFolderClass *class;
+       gboolean success = TRUE;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_val_if_fail (class->expunge_sync != NULL, FALSE);
+
+       camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
+
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+               return FALSE;
+       }
+
+       if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED)) {
+               success = class->expunge_sync (folder, cancellable, error);
+               CAMEL_CHECK_GERROR (folder, expunge_sync, success, error);
+       }
+
+       camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+
+       return success;
+}
+
+/**
+ * camel_folder_expunge:
+ * @folder: a #CamelFolder
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously deletes messages which have been marked as "DELETED".
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_folder_expunge_finish() to get the result of the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_folder_expunge (CamelFolder *folder,
+                      gint io_priority,
+                      GCancellable *cancellable,
+                      GAsyncReadyCallback callback,
+                      gpointer user_data)
+{
+       CamelFolderClass *class;
+
+       g_return_if_fail (CAMEL_IS_FOLDER (folder));
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_if_fail (class->expunge != NULL);
+
+       class->expunge (folder, io_priority, cancellable, callback, user_data);
+}
+
+/**
+ * camel_folder_expunge_finish:
+ * @folder: a #CamelFolder
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_folder_expunge().
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_folder_expunge_finish (CamelFolder *folder,
+                             GAsyncResult *result,
+                             GError **error)
+{
+       CamelFolderClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_val_if_fail (class->expunge_finish != NULL, FALSE);
+
+       return class->expunge_finish (folder, result, error);
+}
+
+/**
+ * camel_folder_get_message_sync:
+ * @folder: a #CamelFolder
+ * @message_uid: the message UID
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets the message corresponding to @message_uid from @folder.
+ *
+ * Returns: a #CamelMimeMessage corresponding to the requested UID
+ *
+ * Since: 2.34
+ **/
+CamelMimeMessage *
+camel_folder_get_message_sync (CamelFolder *folder,
+                               const gchar *message_uid,
+                               GCancellable *cancellable,
+                               GError **error)
+{
+       CamelFolderClass *class;
+       CamelMimeMessage *message;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
+       g_return_val_if_fail (message_uid != NULL, NULL);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_val_if_fail (class->get_message_sync != NULL, NULL);
+
+       camel_operation_push_message (
+               cancellable, _("Retrieving message '%s'"), message_uid);
+
+       camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
+
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+               return NULL;
+       }
+
+       message = class->get_message_sync (
+               folder, message_uid, cancellable, error);
+       CAMEL_CHECK_GERROR (folder, get_message_sync, message != NULL, error);
+
+       camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+
+       camel_operation_pop_message (cancellable);
+
+       if (message != NULL && camel_debug_start (":folder")) {
+               printf ("CamelFolder:get_message ('%s', '%s') =\n",
+                       camel_folder_get_full_name (folder), message_uid);
+               camel_mime_message_dump (message, FALSE);
+               camel_debug_end ();
+       }
+
+       return message;
+}
+
+/**
+ * camel_folder_get_message:
+ * @folder: a #CamelFolder
+ * @message_uid: the message UID
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously gets the message corresponding to @message_uid from @folder.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_folder_get_message_finish() to get the result of the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_folder_get_message (CamelFolder *folder,
+                          const gchar *message_uid,
+                          gint io_priority,
+                          GCancellable *cancellable,
+                          GAsyncReadyCallback callback,
+                          gpointer user_data)
+{
+       CamelFolderClass *class;
+
+       g_return_if_fail (CAMEL_IS_FOLDER (folder));
+       g_return_if_fail (message_uid != NULL);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_if_fail (class->get_message != NULL);
+
+       class->get_message (
+               folder, message_uid, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_folder_get_message_finish:
+ * @folder: a #CamelFolder
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError or %NULL
+ *
+ * Finishes the operation started with camel_folder_get_message().
+ *
+ * Returns: a #CamelMimeMessage corresponding to the requested UID
+ *
+ * Since: 2.34
+ **/
+CamelMimeMessage *
+camel_folder_get_message_finish (CamelFolder *folder,
+                                 GAsyncResult *result,
+                                 GError **error)
+{
+       CamelFolderClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_val_if_fail (class->get_message_finish != NULL, NULL);
+
+       return class->get_message_finish (folder, result, error);
+}
+
+/**
+ * camel_folder_refresh_info_sync:
+ * @folder: a #CamelFolder
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Synchronizes a folder's summary with its backing store.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_folder_refresh_info_sync (CamelFolder *folder,
+                                GCancellable *cancellable,
+                                GError **error)
+{
+       CamelFolderClass *class;
+       gboolean success;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_val_if_fail (class->refresh_info_sync != NULL, FALSE);
+
+       camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
+
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+               return FALSE;
+       }
+
+       success = class->refresh_info_sync (folder, cancellable, error);
+       CAMEL_CHECK_GERROR (folder, refresh_info_sync, success, error);
+
+       camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+
+       return success;
+}
+
+/**
+ * camel_folder_synchronize_sync:
+ * @folder: a #CamelFolder
+ * @expunge: whether to expunge after synchronizing
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Synchronizes any changes that have been made to @folder to its
+ * backing store, optionally expunging deleted messages as well.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_folder_synchronize_sync (CamelFolder *folder,
+                               gboolean expunge,
+                               GCancellable *cancellable,
+                               GError **error)
+{
+       CamelFolderClass *class;
+       gboolean success = TRUE;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_val_if_fail (class->synchronize_sync != NULL, FALSE);
+
+       camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
+
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+               return FALSE;
+       }
+
+       if (!(folder->folder_flags & CAMEL_FOLDER_HAS_BEEN_DELETED)) {
+               success = class->synchronize_sync (
+                       folder, expunge, cancellable, error);
+               CAMEL_CHECK_GERROR (folder, synchronize_sync, success, error);
+       }
+
+       camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+
+       return success;
+}
+
+/**
+ * camel_folder_synchronize:
+ * @folder: a #CamelFolder
+ * @expunge: whether to expunge after synchronizing
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Synchronizes any changes that have been made to @folder to its backing
+ * store asynchronously, optionally expunging deleted messages as well.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_folder_synchronize_finish() to get the result of the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_folder_synchronize (CamelFolder *folder,
+                          gboolean expunge,
+                          gint io_priority,
+                          GCancellable *cancellable,
+                          GAsyncReadyCallback callback,
+                          gpointer user_data)
+{
+       CamelFolderClass *class;
+
+       g_return_if_fail (CAMEL_IS_FOLDER (folder));
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_if_fail (class->synchronize != NULL);
+
+       class->synchronize (
+               folder, expunge, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_folder_synchronize_finish:
+ * @folder: a #CamelFolder
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_folder_synchronize().
+ *
+ * Returns: %TRUE on sucess, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_folder_synchronize_finish (CamelFolder *folder,
+                                 GAsyncResult *result,
+                                 GError **error)
+{
+       CamelFolderClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_val_if_fail (class->synchronize_finish != NULL, FALSE);
+
+       return class->synchronize_finish (folder, result, error);
+}
+
+/**
+ * camel_folder_synchronize_message_sync:
+ * @folder: a #CamelFolder
+ * @message_uid: a message UID
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Ensure that a message identified by @message_uid has been synchronized in
+ * @folder so that calling camel_folder_get_message() on it later will work
+ * in offline mode.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_folder_synchronize_message_sync (CamelFolder *folder,
+                                       const gchar *message_uid,
+                                       GCancellable *cancellable,
+                                       GError **error)
+{
+       CamelFolderClass *class;
+       gboolean success = FALSE;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+       g_return_val_if_fail (message_uid != NULL, FALSE);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_val_if_fail (class->get_message_sync != NULL, FALSE);
+
+       camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
+
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+               return FALSE;
+       }
+
+       /* Use the sync_message method if the class implements it. */
+       if (class->synchronize_message_sync != NULL) {
+               success = class->synchronize_message_sync (
+                       folder, message_uid, cancellable, error);
+               CAMEL_CHECK_GERROR (
+                       folder, synchronize_message_sync, success, error);
+       } else {
+               CamelMimeMessage *message;
+
+               message = class->get_message_sync (
+                       folder, message_uid, cancellable, error);
+               CAMEL_CHECK_GERROR (
+                       folder, get_message_sync, message != NULL, error);
+
+               if (message != NULL) {
+                       g_object_unref (message);
+                       success = TRUE;
+               }
+       }
+
+       camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+
+       return success;
+}
+
+/**
+ * camel_folder_synchronize_message;
+ * @folder: a #CamelFolder
+ * @message_uid: a message UID
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously ensure that a message identified by @message_uid has been
+ * synchronized in @folder so that calling camel_folder_get_message() on it
+ * later will work in offline mode.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_folder_synchronize_message_finish() to get the result of the
+ * operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_folder_synchronize_message (CamelFolder *folder,
+                                  const gchar *message_uid,
+                                  gint io_priority,
+                                  GCancellable *cancellable,
+                                  GAsyncReadyCallback callback,
+                                  gpointer user_data)
+{
+       CamelFolderClass *class;
+
+       g_return_if_fail (CAMEL_IS_FOLDER (folder));
+       g_return_if_fail (message_uid != NULL);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_if_fail (class->synchronize_message != NULL);
+
+       class->synchronize_message (
+               folder, message_uid, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_folder_synchronize_message_finish:
+ * @folder: a #CamelFolder
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_folder_synchronize_message().
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_folder_synchronize_message_finish (CamelFolder *folder,
+                                         GAsyncResult *result,
+                                         GError **error)
+{
+       CamelFolderClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (folder), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_FOLDER_GET_CLASS (folder);
+       g_return_val_if_fail (class->synchronize_message_finish != NULL, FALSE);
+
+       return class->synchronize_message_finish (folder, result, error);
+}
+
+/**
+ * camel_folder_transfer_messages_to_sync:
+ * @source: the source #CamelFolder
+ * @message_uids: message UIDs in @source
+ * @destination: the destination #CamelFolder
+ * @delete_originals: whether or not to delete the original messages
+ * @transferred_uids: if non-%NULL, the UIDs of the resulting messages
+ *                    in @destination will be stored here, if known.
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Copies or moves messages from one folder to another.  If the
+ * @source and @destination folders have the same parent_store, this
+ * may be more efficient than using camel_folder_append_message_sync().
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_folder_transfer_messages_to_sync (CamelFolder *source,
+                                        GPtrArray *message_uids,
+                                        CamelFolder *destination,
+                                        gboolean delete_originals,
+                                        GPtrArray **transferred_uids,
+                                        GCancellable *cancellable,
+                                        GError **error)
+{
+       CamelFolderClass *class;
+       gboolean success;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (source), FALSE);
+       g_return_val_if_fail (CAMEL_IS_FOLDER (destination), FALSE);
+       g_return_val_if_fail (message_uids != NULL, FALSE);
+
+       if (source == destination || message_uids->len == 0)
+               return TRUE;
+
+       if (source->priv->parent_store == destination->priv->parent_store) {
+               /* If either folder is a vtrash, we need to use the
+                * vtrash transfer method. */
+               if (CAMEL_IS_VTRASH_FOLDER (destination))
+                       class = CAMEL_FOLDER_GET_CLASS (destination);
+               else
+                       class = CAMEL_FOLDER_GET_CLASS (source);
+               success = class->transfer_messages_to_sync (
+                       source, message_uids, destination, delete_originals,
+                       transferred_uids, cancellable, error);
+       } else
+               success = folder_transfer_messages_to_sync (
+                       source, message_uids, destination, delete_originals,
+                       transferred_uids, cancellable, error);
+
+       return success;
+}
+
+/**
+ * camel_folder_transfer_messages_to:
+ * @source: the source #CamelFolder
+ * @message_uids: message UIDs in @source
+ * @destination: the destination #CamelFolder
+ * @delete_originals: whether or not to delete the original messages
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously copies or moves messages from one folder to another.
+ * If the @source or @destination folders have the same parent store,
+ * this may be more efficient than using camel_folder_append_message().
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_folder_transfer_messages_to_finish() to get the result of the
+ * operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_folder_transfer_messages_to (CamelFolder *source,
+                                   GPtrArray *message_uids,
+                                   CamelFolder *destination,
+                                   gboolean delete_originals,
+                                   gint io_priority,
+                                   GCancellable *cancellable,
+                                   GAsyncReadyCallback callback,
+                                   gpointer user_data)
+{
+       CamelFolderClass *class;
+
+       g_return_if_fail (CAMEL_IS_FOLDER (source));
+       g_return_if_fail (CAMEL_IS_FOLDER (destination));
+       g_return_if_fail (message_uids != NULL);
+
+       class = CAMEL_FOLDER_GET_CLASS (source);
+       g_return_if_fail (class->transfer_messages_to != NULL);
+
+       class->transfer_messages_to (
+               source, message_uids, destination, delete_originals,
+               io_priority, cancellable, callback, user_data);
+}
+
+/**
+ * camel_folder_transfer_messages_to_finish:
+ * @source: a #CamelFolder
+ * @result: a #GAsyncResult
+ * @transferred_uids: if non-%NULL, the UIDs of the resulting messages
+ *                    in @destination will be stored here, if known.
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_folder_transfer_messages_to().
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_folder_transfer_messages_to_finish (CamelFolder *source,
+                                          GAsyncResult *result,
+                                          GPtrArray **transferred_uids,
+                                          GError **error)
+{
+       CamelFolderClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_FOLDER (source), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_FOLDER_GET_CLASS (source);
+       g_return_val_if_fail (class->transfer_messages_to_finish != NULL, FALSE);
+
+       return class->transfer_messages_to_finish (
+               source, result, transferred_uids, error);
+}
+
+/**
+ * camel_folder_change_info_new:
+ *
+ * Create a new folder change info structure.
+ *
+ * Change info structures are not MT-SAFE and must be
+ * locked for exclusive access externally.
+ *
+ * Returns: a new #CamelFolderChangeInfo
+ **/
+CamelFolderChangeInfo *
+camel_folder_change_info_new (void)
+{
+       CamelFolderChangeInfo *info;
 
        info = g_slice_new (CamelFolderChangeInfo);
        info->uid_added = g_ptr_array_new ();
@@ -2991,59 +4025,3 @@ camel_folder_change_info_free (CamelFolderChangeInfo *info)
        g_ptr_array_free (info->uid_recent, TRUE);
        g_slice_free (CamelFolderChangeInfo, info);
 }
-
-/**
- * camel_folder_lock:
- * @folder: a #CamelFolder
- * @lock: lock type to lock
- *
- * Locks #folder's #lock. Unlock it with camel_folder_unlock().
- *
- * Since: 2.32
- **/
-void
-camel_folder_lock (CamelFolder *folder,
-                   CamelFolderLock lock)
-{
-       g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
-       switch (lock) {
-               case CAMEL_FOLDER_CHANGE_LOCK:
-                       g_static_mutex_lock (&folder->priv->change_lock);
-                       break;
-               case CAMEL_FOLDER_REC_LOCK:
-                       if (folder->priv->skip_folder_lock == FALSE)
-                               g_static_rec_mutex_lock (&folder->priv->lock);
-                       break;
-               default:
-                       g_return_if_reached ();
-       }
-}
-
-/**
- * camel_folder_unlock:
- * @folder: a #CamelFolder
- * @lock: lock type to unlock
- *
- * Unlocks #folder's #lock, previously locked with camel_folder_lock().
- *
- * Since: 2.32
- **/
-void
-camel_folder_unlock (CamelFolder *folder,
-                     CamelFolderLock lock)
-{
-       g_return_if_fail (CAMEL_IS_FOLDER (folder));
-
-       switch (lock) {
-               case CAMEL_FOLDER_CHANGE_LOCK:
-                       g_static_mutex_unlock (&folder->priv->change_lock);
-                       break;
-               case CAMEL_FOLDER_REC_LOCK:
-                       if (folder->priv->skip_folder_lock == FALSE)
-                               g_static_rec_mutex_unlock (&folder->priv->lock);
-                       break;
-               default:
-                       g_return_if_reached ();
-       }
-}
index 652cba7..0fb551b 100644 (file)
@@ -143,7 +143,7 @@ struct _CamelFolder {
 struct _CamelFolderClass {
        CamelObjectClass parent_class;
 
-       /* Methods */
+       /* Non-Blocking Methods */
        gint            (*get_message_count)    (CamelFolder *folder);
        guint32         (*get_permanent_flags)  (CamelFolder *folder);
        guint32         (*get_message_flags)    (CamelFolder *folder,
@@ -212,9 +212,10 @@ struct _CamelFolderClass {
                                                 const gchar *uid,
                                                 GError **error);
 
+       /* Synchronous I/O Methods */
        gboolean        (*append_message_sync)  (CamelFolder *folder,
                                                 CamelMimeMessage *message,
-                                                const CamelMessageInfo *info,
+                                                CamelMessageInfo *info,
                                                 gchar **appended_uid,
                                                 GCancellable *cancellable,
                                                 GError **error);
@@ -223,7 +224,7 @@ struct _CamelFolderClass {
                                                 GError **error);
        CamelMimeMessage *
                        (*get_message_sync)     (CamelFolder *folder,
-                                                const gchar *uid,
+                                                const gchar *message_uid,
                                                 GCancellable *cancellable,
                                                 GError **error);
        gboolean        (*refresh_info_sync)    (CamelFolder *folder,
@@ -235,16 +236,88 @@ struct _CamelFolderClass {
                                                 GError **error);
        gboolean        (*synchronize_message_sync)
                                                (CamelFolder *folder,
-                                                const gchar *uid,
+                                                const gchar *message_uid,
                                                 GCancellable *cancellable,
                                                 GError **error);
        gboolean        (*transfer_messages_to_sync)
                                                (CamelFolder *source,
-                                                GPtrArray *uids,
+                                                GPtrArray *message_uids,
                                                 CamelFolder *destination,
+                                                gboolean delete_originals,
                                                 GPtrArray **transferred_uids,
+                                                GCancellable *cancellable,
+                                                GError **error);
+
+       /* Asynchronous I/O Methods (all have defaults) */
+       void            (*append_message)       (CamelFolder *folder,
+                                                CamelMimeMessage *message,
+                                                CamelMessageInfo *info,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*append_message_finish)
+                                               (CamelFolder *folder,
+                                                GAsyncResult *result,
+                                                gchar **appended_uid,
+                                                GError **error);
+       void            (*expunge)              (CamelFolder *folder,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*expunge_finish)       (CamelFolder *folder,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*get_message)          (CamelFolder *folder,
+                                                const gchar *message_uid,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       CamelMimeMessage *
+                       (*get_message_finish)   (CamelFolder *folder,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*refresh_info)         (CamelFolder *folder,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*refresh_info_finish)  (CamelFolder *folder,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*synchronize)          (CamelFolder *folder,
+                                                gboolean expunge,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*synchronize_finish)   (CamelFolder *folder,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*synchronize_message)  (CamelFolder *folder,
+                                                const gchar *message_uid,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*synchronize_message_finish)
+                                               (CamelFolder *folder,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*transfer_messages_to) (CamelFolder *source,
+                                                GPtrArray *message_uids,
+                                                CamelFolder *destination,
                                                 gboolean delete_originals,
+                                                gint io_priority,
                                                 GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*transfer_messages_to_finish)
+                                               (CamelFolder *source,
+                                                GAsyncResult *result,
+                                                GPtrArray **transferred_uids,
                                                 GError **error);
 
        /* Signals */
@@ -378,40 +451,118 @@ void             camel_folder_free_deep          (CamelFolder *folder,
 gchar *                camel_folder_get_filename       (CamelFolder *folder,
                                                 const gchar *uid,
                                                 GError **error);
+void           camel_folder_lock               (CamelFolder *folder,
+                                                CamelFolderLock lock);
+void           camel_folder_unlock             (CamelFolder *folder,
+                                                CamelFolderLock lock);
+
 gboolean       camel_folder_append_message_sync
                                                (CamelFolder *folder,
                                                 CamelMimeMessage *message,
-                                                const CamelMessageInfo *info,
+                                                CamelMessageInfo *info,
                                                 gchar **appended_uid,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_folder_append_message     (CamelFolder *folder,
+                                                CamelMimeMessage *message,
+                                                CamelMessageInfo *info,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_folder_append_message_finish
+                                               (CamelFolder *folder,
+                                                GAsyncResult *result,
+                                                gchar **appended_uid,
+                                                GError **error);
 gboolean       camel_folder_expunge_sync       (CamelFolder *folder,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_folder_expunge            (CamelFolder *folder,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_folder_expunge_finish     (CamelFolder *folder,
+                                                GAsyncResult *result,
+                                                GError **error);
 CamelMimeMessage *
                camel_folder_get_message_sync   (CamelFolder *folder,
-                                                const gchar *uid,
+                                                const gchar *message_uid,
+                                                GCancellable *cancellable,
+                                                GError **error);
+void           camel_folder_get_message        (CamelFolder *folder,
+                                                const gchar *message_uid,
+                                                gint io_priority,
                                                 GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+CamelMimeMessage *
+               camel_folder_get_message_finish (CamelFolder *folder,
+                                                GAsyncResult *result,
                                                 GError **error);
 gboolean       camel_folder_refresh_info_sync  (CamelFolder *folder,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_folder_refresh_info       (CamelFolder *folder,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_folder_refresh_info_finish
+                                               (CamelFolder *folder,
+                                                GAsyncResult *result,
+                                                GError **error);
 gboolean       camel_folder_synchronize_sync   (CamelFolder *folder,
                                                 gboolean expunge,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_folder_synchronize        (CamelFolder *folder,
+                                                gboolean expunge,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_folder_synchronize_finish (CamelFolder *folder,
+                                                GAsyncResult *result,
+                                                GError **error);
 gboolean       camel_folder_synchronize_message_sync
                                                (CamelFolder *folder,
-                                                const gchar *uid,
+                                                const gchar *message_uid,
+                                                GCancellable *cancellable,
+                                                GError **error);
+void           camel_folder_synchronize_message
+                                               (CamelFolder *folder,
+                                                const gchar *message_uid,
+                                                gint io_priority,
                                                 GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_folder_synchronize_message_finish
+                                               (CamelFolder *folder,
+                                                GAsyncResult *result,
                                                 GError **error);
 gboolean       camel_folder_transfer_messages_to_sync
                                                (CamelFolder *source,
-                                                GPtrArray *uids,
-                                                CamelFolder *dest,
+                                                GPtrArray *message_uids,
+                                                CamelFolder *destination,
+                                                gboolean delete_originals,
                                                 GPtrArray **transferred_uids,
+                                                GCancellable *cancellable,
+                                                GError **error);
+void           camel_folder_transfer_messages_to
+                                               (CamelFolder *source,
+                                                GPtrArray *message_uids,
+                                                CamelFolder *destination,
                                                 gboolean delete_originals,
+                                                gint io_priority,
                                                 GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_folder_transfer_messages_to_finish
+                                               (CamelFolder *source,
+                                                GAsyncResult *result,
+                                                GPtrArray **transferred_uids,
                                                 GError **error);
 
 /* update functions for change info */
@@ -452,11 +603,6 @@ void               camel_folder_change_info_recent_uid
                                                (CamelFolderChangeInfo *info,
                                                 const gchar *uid);
 
-void           camel_folder_lock               (CamelFolder *folder,
-                                                CamelFolderLock lock);
-void           camel_folder_unlock             (CamelFolder *folder,
-                                                CamelFolderLock lock);
-
 G_END_DECLS
 
 #endif /* CAMEL_FOLDER_H */
index a63257f..f027917 100644 (file)
@@ -1506,7 +1506,7 @@ gpg_id_to_hash (CamelCipherContext *context,
        return CAMEL_CIPHER_HASH_DEFAULT;
 }
 
-static gint
+static gboolean
 gpg_sign_sync (CamelCipherContext *context,
                const gchar *userid,
                CamelCipherHash hash,
@@ -1520,9 +1520,9 @@ gpg_sign_sync (CamelCipherContext *context,
        CamelStream *ostream = camel_stream_mem_new (), *istream;
        CamelDataWrapper *dw;
        CamelContentType *ct;
-       gint res = -1;
        CamelMimePart *sigpart;
        CamelMultipartSigned *mps;
+       gboolean success = FALSE;
 
        /* Note: see rfc2015 or rfc3156, section 5 */
 
@@ -1588,7 +1588,7 @@ gpg_sign_sync (CamelCipherContext *context,
                goto fail;
        }
 
-       res = 0;
+       success = TRUE;
 
        dw = camel_data_wrapper_new ();
        camel_stream_reset (ostream, NULL);
@@ -1608,7 +1608,7 @@ gpg_sign_sync (CamelCipherContext *context,
 
        mps = camel_multipart_signed_new ();
        ct = camel_content_type_new("multipart", "signed");
-       camel_content_type_set_param(ct, "micalg", camel_cipher_hash_to_id (context, hash == CAMEL_CIPHER_HASH_DEFAULT ? gpg->hash : hash));
+       camel_content_type_set_param(ct, "micalg", camel_cipher_context_hash_to_id (context, hash == CAMEL_CIPHER_HASH_DEFAULT ? gpg->hash : hash));
        camel_content_type_set_param(ct, "protocol", class->sign_protocol);
        camel_data_wrapper_set_mime_type_field ((CamelDataWrapper *)mps, ct);
        camel_content_type_unref (ct);
@@ -1626,7 +1626,7 @@ fail:
        if (gpg)
                gpg_ctx_free (gpg);
 
-       return res;
+       return success;
 }
 
 static CamelCipherValidity *
@@ -1689,8 +1689,9 @@ gpg_verify_sync (CamelCipherContext *context,
                CamelDataWrapper *content;
                content = camel_medium_get_content ((CamelMedium *) ipart);
                istream = camel_stream_mem_new ();
-               camel_data_wrapper_decode_to_stream_sync (
-                       content, istream, NULL, NULL);
+               if (!camel_data_wrapper_decode_to_stream_sync (
+                       content, istream, cancellable, error))
+                       goto exception;
                camel_stream_reset (istream, NULL);
                sigpart = NULL;
        } else {
@@ -1831,7 +1832,7 @@ gpg_verify_sync (CamelCipherContext *context,
        return NULL;
 }
 
-static gint
+static gboolean
 gpg_encrypt_sync (CamelCipherContext *context,
                   const gchar *userid,
                   GPtrArray *recipients,
@@ -1843,12 +1844,13 @@ gpg_encrypt_sync (CamelCipherContext *context,
        CamelCipherContextClass *class;
        CamelGpgContext *ctx = (CamelGpgContext *) context;
        struct _GpgCtx *gpg;
-       gint i, res = -1;
        CamelStream *istream, *ostream, *vstream;
        CamelMimePart *encpart, *verpart;
        CamelDataWrapper *dw;
        CamelContentType *ct;
        CamelMultipartEncrypted *mpe;
+       gboolean success = FALSE;
+       gint i;
 
        class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
 
@@ -1895,7 +1897,7 @@ gpg_encrypt_sync (CamelCipherContext *context,
                goto fail;
        }
 
-       res = 0;
+       success = TRUE;
 
        dw = camel_data_wrapper_new ();
        camel_data_wrapper_construct_from_stream_sync (
@@ -1946,7 +1948,7 @@ fail1:
        g_object_unref (istream);
        g_object_unref (ostream);
 
-       return res;
+       return success;
 }
 
 static CamelCipherValidity *
@@ -1956,14 +1958,14 @@ gpg_decrypt_sync (CamelCipherContext *context,
                   GCancellable *cancellable,
                   GError **error)
 {
-       struct _GpgCtx *gpg;
+       struct _GpgCtx *gpg = NULL;
        CamelCipherValidity *valid = NULL;
        CamelStream *ostream, *istream;
        CamelDataWrapper *content;
        CamelMimePart *encrypted;
        CamelMultipart *mp;
        CamelContentType *ct;
-       gint rv;
+       gboolean success;
 
        if (!ipart) {
                g_set_error (
@@ -2005,8 +2007,9 @@ gpg_decrypt_sync (CamelCipherContext *context,
        }
 
        istream = camel_stream_mem_new ();
-       camel_data_wrapper_decode_to_stream_sync (
-               content, istream, NULL, NULL);
+       if (!camel_data_wrapper_decode_to_stream_sync (
+               content, istream, cancellable, error))
+               goto fail;
        camel_stream_reset (istream, NULL);
 
        ostream = camel_stream_mem_new ();
@@ -2044,7 +2047,7 @@ gpg_decrypt_sync (CamelCipherContext *context,
                CamelStream *null = camel_stream_null_new ();
 
                /* Multipart encrypted - parse a full mime part */
-               rv = camel_data_wrapper_construct_from_stream_sync (
+               success = camel_data_wrapper_construct_from_stream_sync (
                        CAMEL_DATA_WRAPPER (opart),
                        ostream, NULL, error);
 
@@ -2054,8 +2057,8 @@ gpg_decrypt_sync (CamelCipherContext *context,
                        /* nothing had been decoded from the stream, it doesn't
                           contain any header, like Content-Type or such, thus
                           write it as a message body */
-                       rv = camel_data_wrapper_construct_from_stream_sync (
-                               dw, ostream, NULL, error);
+                       success = camel_data_wrapper_construct_from_stream_sync (
+                               dw, ostream, cancellable, error);
                }
 
                g_object_unref (null);
@@ -2063,7 +2066,7 @@ gpg_decrypt_sync (CamelCipherContext *context,
                /* Inline signed - raw data (may not be a mime part) */
                CamelDataWrapper *dw;
                dw = camel_data_wrapper_new ();
-               rv = camel_data_wrapper_construct_from_stream_sync (
+               success = camel_data_wrapper_construct_from_stream_sync (
                        dw, ostream, NULL, error);
                camel_data_wrapper_set_mime_type(dw, "application/octet-stream");
                camel_medium_set_content ((CamelMedium *)opart, dw);
@@ -2072,7 +2075,7 @@ gpg_decrypt_sync (CamelCipherContext *context,
                camel_mime_part_set_content_type(opart, "application/octet-stream");
        }
 
-       if (rv != -1) {
+       if (success) {
                valid = camel_cipher_validity_new ();
                valid->encrypt.description = g_strdup(_("Encrypted content"));
                valid->encrypt.status = CAMEL_CIPHER_VALIDITY_ENCRYPT_ENCRYPTED;
@@ -2103,14 +2106,14 @@ gpg_decrypt_sync (CamelCipherContext *context,
        return valid;
 }
 
-static gint
+static gboolean
 gpg_import_keys_sync (CamelCipherContext *context,
                       CamelStream *istream,
                       GCancellable *cancellable,
                       GError **error)
 {
        struct _GpgCtx *gpg;
-       gint res = -1;
+       gboolean success = FALSE;
 
        gpg = gpg_ctx_new (context);
        gpg_ctx_set_mode (gpg, GPG_CTX_MODE_IMPORT);
@@ -2137,14 +2140,14 @@ gpg_import_keys_sync (CamelCipherContext *context,
                goto fail;
        }
 
-       res = 0;
+       success = TRUE;
 fail:
        gpg_ctx_free (gpg);
 
-       return res;
+       return success;
 }
 
-static gint
+static gboolean
 gpg_export_keys_sync (CamelCipherContext *context,
                       GPtrArray *keys,
                       CamelStream *ostream,
@@ -2152,8 +2155,8 @@ gpg_export_keys_sync (CamelCipherContext *context,
                       GError **error)
 {
        struct _GpgCtx *gpg;
+       gboolean success = FALSE;
        gint i;
-       gint res = -1;
 
        gpg = gpg_ctx_new (context);
        gpg_ctx_set_mode (gpg, GPG_CTX_MODE_EXPORT);
@@ -2185,11 +2188,11 @@ gpg_export_keys_sync (CamelCipherContext *context,
                goto fail;
        }
 
-       res = 0;
+       success = TRUE;
 fail:
        gpg_ctx_free (gpg);
 
-       return res;
+       return success;
 }
 
 static void
index ba97e3a..217b85c 100644 (file)
@@ -288,7 +288,7 @@ mime_message_remove_header (CamelMedium *medium,
        CAMEL_MEDIUM_CLASS (camel_mime_message_parent_class)->remove_header (medium, name);
 }
 
-static gint
+static gboolean
 mime_message_construct_from_parser_sync (CamelMimePart *dw,
                                          CamelMimeParser *mp,
                                          GCancellable *cancellable,
@@ -298,16 +298,16 @@ mime_message_construct_from_parser_sync (CamelMimePart *dw,
        gchar *buf;
        gsize len;
        gint state;
-       gint ret;
        gint err;
+       gboolean success;
 
        /* let the mime-part construct the guts ... */
        mime_part_class = CAMEL_MIME_PART_CLASS (camel_mime_message_parent_class);
-       ret = mime_part_class->construct_from_parser_sync (
+       success = mime_part_class->construct_from_parser_sync (
                dw, mp, cancellable, error);
 
-       if (ret == -1)
-               return -1;
+       if (!success)
+               return FALSE;
 
        /* ... then clean up the follow-on state */
        state = camel_mime_parser_step (mp, &buf, &len);
@@ -321,7 +321,7 @@ mime_message_construct_from_parser_sync (CamelMimePart *dw,
        default:
                g_error ("Bad parser state: Expecing MESSAGE_END or EOF or EOM, got: %u", camel_mime_parser_state (mp));
                camel_mime_parser_unstep (mp);
-               return -1;
+               return FALSE;
        }
 
        err = camel_mime_parser_errno (mp);
@@ -331,10 +331,10 @@ mime_message_construct_from_parser_sync (CamelMimePart *dw,
                        error, G_IO_ERROR,
                        g_io_error_from_errno (errno),
                        "%s", g_strerror (errno));
-               ret = -1;
+               success = FALSE;
        }
 
-       return ret;
+       return success;
 }
 
 static void
@@ -845,7 +845,10 @@ camel_mime_message_has_8bit_parts (CamelMimeMessage *msg)
 
 /* finds the best charset and transfer encoding for a given part */
 static CamelTransferEncoding
-find_best_encoding (CamelMimePart *part, CamelBestencRequired required, CamelBestencEncoding enctype, gchar **charsetp)
+find_best_encoding (CamelMimePart *part,
+                    CamelBestencRequired required,
+                    CamelBestencEncoding enctype,
+                    gchar **charsetp)
 {
        CamelMimeFilter *charenc = NULL;
        CamelTransferEncoding encoding;
@@ -1034,7 +1037,9 @@ best_encoding (CamelMimeMessage *msg, CamelMimePart *part, gpointer datap)
  * parts will be encoded as binary and 8bit textual parts will be encoded as 8bit.
  **/
 void
-camel_mime_message_set_best_encoding (CamelMimeMessage *msg, CamelBestencRequired required, CamelBestencEncoding enctype)
+camel_mime_message_set_best_encoding (CamelMimeMessage *msg,
+                                      CamelBestencRequired required,
+                                      CamelBestencEncoding enctype)
 {
        struct _enc_data data;
 
index f4cac90..3f6ae1f 100644 (file)
@@ -93,55 +93,63 @@ struct _CamelMimeMessageClass {
        CamelMimePartClass parent_class;
 };
 
-GType                   camel_mime_message_get_type           (void);
-
-/* public methods */
-CamelMimeMessage           *camel_mime_message_new                (void);
-void                        camel_mime_message_set_date           (CamelMimeMessage           *message,
-                                                                  time_t                      date,
-                                                                  gint                         offset);
-time_t                      camel_mime_message_get_date           (CamelMimeMessage           *message,
-                                                                  gint                        *offset);
-time_t                      camel_mime_message_get_date_received  (CamelMimeMessage           *message,
-                                                                  gint                        *offset);
-void                        camel_mime_message_set_message_id     (CamelMimeMessage           *message,
-                                                                  const gchar                 *message_id);
-const gchar                 *camel_mime_message_get_message_id     (CamelMimeMessage           *message);
-void                        camel_mime_message_set_reply_to       (CamelMimeMessage           *message,
-                                                                  CamelInternetAddress *reply_to);
-CamelInternetAddress *      camel_mime_message_get_reply_to       (CamelMimeMessage           *message);
-
-void                        camel_mime_message_set_subject        (CamelMimeMessage           *message,
-                                                                  const gchar                 *subject);
-const gchar                 *camel_mime_message_get_subject        (CamelMimeMessage           *message);
-void                        camel_mime_message_set_from           (CamelMimeMessage           *message,
-                                                                  CamelInternetAddress *from);
-CamelInternetAddress *      camel_mime_message_get_from           (CamelMimeMessage           *message);
-
-CamelInternetAddress *      camel_mime_message_get_recipients     (CamelMimeMessage           *message,
-                                                                  const gchar                 *type);
-void                        camel_mime_message_set_recipients     (CamelMimeMessage           *message,
-                                                                  const gchar                 *type,
-                                                                  CamelInternetAddress *recipients);
-
-void                        camel_mime_message_set_source         (CamelMimeMessage           *message,
-                                                                  const gchar                 *identity);
-const gchar                 *camel_mime_message_get_source         (CamelMimeMessage           *message);
+GType          camel_mime_message_get_type     (void);
+CamelMimeMessage *
+               camel_mime_message_new          (void);
+void           camel_mime_message_set_date     (CamelMimeMessage *message,
+                                                time_t date,
+                                                gint offset);
+time_t         camel_mime_message_get_date     (CamelMimeMessage *message,
+                                                gint *offset);
+time_t         camel_mime_message_get_date_received
+                                               (CamelMimeMessage *message,
+                                                gint *offset);
+void           camel_mime_message_set_message_id
+                                               (CamelMimeMessage *message,
+                                                const gchar *message_id);
+const gchar *  camel_mime_message_get_message_id
+                                                (CamelMimeMessage *message);
+void           camel_mime_message_set_reply_to (CamelMimeMessage *message,
+                                                CamelInternetAddress *reply_to);
+CamelInternetAddress *
+               camel_mime_message_get_reply_to (CamelMimeMessage *message);
+void           camel_mime_message_set_subject  (CamelMimeMessage *message,
+                                                const gchar *subject);
+const gchar *  camel_mime_message_get_subject  (CamelMimeMessage *message);
+void           camel_mime_message_set_from     (CamelMimeMessage *message,
+                                                CamelInternetAddress *from);
+CamelInternetAddress *
+               camel_mime_message_get_from     (CamelMimeMessage *message);
+CamelInternetAddress *
+               camel_mime_message_get_recipients
+                                               (CamelMimeMessage *message,
+                                                const gchar *type);
+void           camel_mime_message_set_recipients
+                                               (CamelMimeMessage *message,
+                                                const gchar *type,
+                                                CamelInternetAddress *recipients);
+void           camel_mime_message_set_source   (CamelMimeMessage *message,
+                                                const gchar *identity);
+const gchar *  camel_mime_message_get_source   (CamelMimeMessage *message);
 
 /* utility functions */
-gboolean                    camel_mime_message_has_8bit_parts     (CamelMimeMessage           *message);
-void                        camel_mime_message_set_best_encoding  (CamelMimeMessage           *message,
-                                                                  CamelBestencRequired        required,
-                                                                  CamelBestencEncoding        enctype);
-void                        camel_mime_message_encode_8bit_parts  (CamelMimeMessage           *message);
-
-CamelMimePart              *camel_mime_message_get_part_by_content_id (CamelMimeMessage *message, const gchar *content_id);
-
-gchar                       *camel_mime_message_build_mbox_from    (CamelMimeMessage           *message);
-
-gboolean                   camel_mime_message_has_attachment     (CamelMimeMessage           *message);
-
-void camel_mime_message_dump (CamelMimeMessage *msg, gint body);
+gboolean       camel_mime_message_has_8bit_parts
+                                               (CamelMimeMessage *message);
+void           camel_mime_message_set_best_encoding
+                                               (CamelMimeMessage *message,
+                                                CamelBestencRequired required,
+                                                CamelBestencEncoding enctype);
+void           camel_mime_message_encode_8bit_parts
+                                               (CamelMimeMessage *message);
+CamelMimePart *        camel_mime_message_get_part_by_content_id
+                                               (CamelMimeMessage *message,
+                                                const gchar *content_id);
+gchar *                camel_mime_message_build_mbox_from
+                                               (CamelMimeMessage *message);
+gboolean       camel_mime_message_has_attachment
+                                               (CamelMimeMessage *message);
+void           camel_mime_message_dump         (CamelMimeMessage *message,
+                                                gint body);
 
 G_END_DECLS
 
index e9c7268..b9aad19 100644 (file)
@@ -64,7 +64,7 @@ simple_data_wrapper_construct_from_parser (CamelDataWrapper *dw,
        GByteArray *buffer;
        CamelStream *mem;
        gsize len;
-       gint retval;
+       gboolean success;
 
        d(printf ("simple_data_wrapper_construct_from_parser()\n"));
 
@@ -78,11 +78,11 @@ simple_data_wrapper_construct_from_parser (CamelDataWrapper *dw,
        d(printf("message part kept in memory!\n"));
 
        mem = camel_stream_mem_new_with_byte_array (buffer);
-       retval = camel_data_wrapper_construct_from_stream_sync (
+       success = camel_data_wrapper_construct_from_stream_sync (
                dw, mem, cancellable, error);
        g_object_unref (mem);
 
-       return (retval == 0);
+       return success;
 }
 
 /**
@@ -123,8 +123,8 @@ camel_mime_part_construct_content_from_parser (CamelMimePart *dw,
        case CAMEL_MIME_PARSER_STATE_MESSAGE:
                d(printf("Creating message part\n"));
                content = (CamelDataWrapper *) camel_mime_message_new ();
-               success = (camel_mime_part_construct_from_parser_sync (
-                       (CamelMimePart *)content, mp, cancellable, error) == 0);
+               success = camel_mime_part_construct_from_parser_sync (
+                       (CamelMimePart *)content, mp, cancellable, error);
                break;
        case CAMEL_MIME_PARSER_STATE_MULTIPART:
                d(printf("Creating multi-part\n"));
@@ -160,6 +160,12 @@ camel_mime_part_construct_content_from_parser (CamelMimePart *dw,
 /**
  * camel_mime_message_build_preview:
  *
+ * <note>
+ *   <para>
+ *     This function blocks like crazy.
+ *   </para>
+ * </note>
+ *
  * Since: 2.28
  **/
 gboolean
@@ -186,6 +192,8 @@ camel_mime_message_build_preview (CamelMimePart *msg,
                /*    !camel_content_type_is (dw->mime_type, "text", "html") && */
                    !camel_content_type_is (dw->mime_type, "text", "calendar")) {
                CamelStream *mstream, *bstream;
+
+               /* FIXME Pass a GCancellable and GError here. */
                mstream = camel_stream_mem_new ();
                if (camel_data_wrapper_decode_to_stream_sync (dw, mstream, NULL, NULL) > 0) {
                        gchar *line = NULL;
index e4d7025..8b5bc99 100644 (file)
@@ -53,9 +53,9 @@
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), CAMEL_TYPE_MIME_PART, CamelMimePartPrivate))
 
-struct _CamelMimePartPrivate {
+typedef struct _AsyncContext AsyncContext;
 
-       /* TODO: these should be in a camelcontentinfo */
+struct _CamelMimePartPrivate {
        gchar *description;
        CamelContentDisposition *disposition;
        gchar *content_id;
@@ -65,6 +65,11 @@ struct _CamelMimePartPrivate {
        CamelTransferEncoding encoding;
 };
 
+struct _AsyncContext {
+       /* arguments */
+       CamelMimeParser *parser;
+};
+
 enum {
        PROP_0,
        PROP_CONTENT_ID,
@@ -92,6 +97,15 @@ static GHashTable *header_formatted_table;
 
 G_DEFINE_TYPE (CamelMimePart, camel_mime_part, CAMEL_TYPE_MEDIUM)
 
+static void
+async_context_free (AsyncContext *async_context)
+{
+       if (async_context->parser != NULL)
+               g_object_unref (async_context->parser);
+
+       g_slice_free (AsyncContext, async_context);
+}
+
 static gssize
 write_header (CamelStream *stream,
               const gchar *name,
@@ -671,31 +685,32 @@ mime_part_write_to_stream_sync (CamelDataWrapper *dw,
        return total;
 }
 
-static gint
+static gboolean
 mime_part_construct_from_stream_sync (CamelDataWrapper *dw,
-                                      CamelStream *s,
+                                      CamelStream *stream,
                                       GCancellable *cancellable,
                                       GError **error)
 {
-       CamelMimeParser *mp;
-       gint ret;
+       CamelMimeParser *parser;
+       gboolean success;
 
        d(printf("mime_part::construct_from_stream()\n"));
 
-       mp = camel_mime_parser_new ();
-       if (camel_mime_parser_init_with_stream (mp, s, error) == -1) {
-               ret = -1;
+       parser = camel_mime_parser_new ();
+       if (camel_mime_parser_init_with_stream (parser, stream, error) == -1) {
+               success = FALSE;
        } else {
-               ret = camel_mime_part_construct_from_parser_sync (
-                       CAMEL_MIME_PART (dw), mp, cancellable, error);
+               success = camel_mime_part_construct_from_parser_sync (
+                       CAMEL_MIME_PART (dw), parser, cancellable, error);
        }
-       g_object_unref (mp);
-       return ret;
+       g_object_unref (parser);
+
+       return success;
 }
 
-static gint
+static gboolean
 mime_part_construct_from_parser_sync (CamelMimePart *mime_part,
-                                      CamelMimeParser *mp,
+                                      CamelMimeParser *parser,
                                       GCancellable *cancellable,
                                       GError **error)
 {
@@ -705,10 +720,9 @@ mime_part_construct_from_parser_sync (CamelMimePart *mime_part,
        gchar *buf;
        gsize len;
        gint err;
-       gboolean success;
-       gboolean retval = 0;
+       gboolean success = TRUE;
 
-       switch (camel_mime_parser_step (mp, &buf, &len)) {
+       switch (camel_mime_parser_step (parser, &buf, &len)) {
        case CAMEL_MIME_PARSER_STATE_MESSAGE:
                /* set the default type of a message always */
                if (dw->mime_type)
@@ -717,7 +731,7 @@ mime_part_construct_from_parser_sync (CamelMimePart *mime_part,
        case CAMEL_MIME_PARSER_STATE_HEADER:
        case CAMEL_MIME_PARSER_STATE_MULTIPART:
                /* we have the headers, build them into 'us' */
-               headers = camel_mime_parser_headers_raw (mp);
+               headers = camel_mime_parser_headers_raw (parser);
 
                /* if content-type exists, process it first, set for fallback charset in headers */
                content = camel_header_raw_find(&headers, "content-type", NULL);
@@ -734,24 +748,89 @@ mime_part_construct_from_parser_sync (CamelMimePart *mime_part,
                }
 
                success = camel_mime_part_construct_content_from_parser (
-                       mime_part, mp, cancellable, error);
-               retval = success ? 0 : -1;
+                       mime_part, parser, cancellable, error);
                break;
        default:
-               g_warning("Invalid state encountered???: %u", camel_mime_parser_state(mp));
+               g_warning("Invalid state encountered???: %u", camel_mime_parser_state(parser));
        }
 
-       err = camel_mime_parser_errno (mp);
+       err = camel_mime_parser_errno (parser);
        if (err != 0) {
                errno = err;
                g_set_error (
                        error, G_IO_ERROR,
                        g_io_error_from_errno (errno),
                        "%s", g_strerror (errno));
-               retval = -1;
+               success = FALSE;
+       }
+
+       return success;
+}
+
+static void
+mime_part_construct_from_parser_thread (GSimpleAsyncResult *simple,
+                                        GObject *object,
+                                        GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_mime_part_construct_from_parser_sync (
+               CAMEL_MIME_PART (object), async_context->parser,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
        }
+}
+
+static void
+mime_part_construct_from_parser (CamelMimePart *mime_part,
+                                 CamelMimeParser *parser,
+                                 gint io_priority,
+                                 GCancellable *cancellable,
+                                 GAsyncReadyCallback callback,
+                                 gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->parser = g_object_ref (parser);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (mime_part), callback, user_data,
+               mime_part_construct_from_parser);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, mime_part_construct_from_parser_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+mime_part_construct_from_parser_finish (CamelMimePart *mime_part,
+                                        GAsyncResult *result,
+                                        GError **error)
+{
+       GSimpleAsyncResult *simple;
 
-       return retval;
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (mime_part),
+               mime_part_construct_from_parser), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
 }
 
 static void
@@ -782,6 +861,8 @@ camel_mime_part_class_init (CamelMimePartClass *class)
        data_wrapper_class->construct_from_stream_sync = mime_part_construct_from_stream_sync;
 
        class->construct_from_parser_sync = mime_part_construct_from_parser_sync;
+       class->construct_from_parser = mime_part_construct_from_parser;
+       class->construct_from_parser_finish = mime_part_construct_from_parser_finish;
 
        g_object_class_install_property (
                object_class,
@@ -842,245 +923,264 @@ camel_mime_part_init (CamelMimePart *mime_part)
        data_wrapper->mime_type = camel_content_type_new ("text", "plain");
 }
 
-/* **** Content-Description */
+/**
+ * camel_mime_part_new:
+ *
+ * Create a new MIME part.
+ *
+ * Returns: a new #CamelMimePart
+ **/
+CamelMimePart *
+camel_mime_part_new (void)
+{
+       return g_object_new (CAMEL_TYPE_MIME_PART, NULL);
+}
 
 /**
- * camel_mime_part_set_description:
- * @mime_part: a #CamelMimePart object
- * @description: description of the MIME part
+ * camel_mime_part_set_content:
+ * @mime_part: a #CamelMimePart
+ * @data: data to put into the part
+ * @length: length of @data
+ * @type: Content-Type of the data
  *
- * Set a description on the MIME part.
+ * Utility function used to set the content of a mime part object to
+ * be the provided data. If @length is 0, this routine can be used as
+ * a way to remove old content (in which case @data and @type are
+ * ignored and may be %NULL).
  **/
 void
-camel_mime_part_set_description (CamelMimePart *mime_part,
-                                 const gchar *description)
+camel_mime_part_set_content (CamelMimePart *mime_part,
+                             const gchar *data,
+                             gint length,
+                             const gchar *type) /* why on earth is the type last? */
 {
-       CamelMedium *medium;
-       gchar *text;
+       CamelMedium *medium = CAMEL_MEDIUM (mime_part);
 
-       g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
-       g_return_if_fail (description != NULL);
+       if (length) {
+               CamelDataWrapper *dw;
+               CamelStream *stream;
 
-       medium = CAMEL_MEDIUM (mime_part);
+               dw = camel_data_wrapper_new ();
+               camel_data_wrapper_set_mime_type (dw, type);
+               stream = camel_stream_mem_new_with_buffer (data, length);
+               camel_data_wrapper_construct_from_stream_sync (
+                       dw, stream, NULL, NULL);
+               g_object_unref (stream);
+               camel_medium_set_content (medium, dw);
+               g_object_unref (dw);
+       } else
+               camel_medium_set_content (medium, NULL);
+}
 
-       text = camel_header_encode_string ((guchar *) description);
-       camel_medium_set_header (medium, "Content-Description", text);
-       g_free (text);
+/**
+ * camel_mime_part_get_content_disposition:
+ * @mime_part: a #CamelMimePart
+ *
+ * Get the disposition of the MIME part as a structure.
+ * Returned pointer is owned by #mime_part.
+ *
+ * Returns: the disposition structure
+ *
+ * Since: 2.30
+ **/
+const CamelContentDisposition *
+camel_mime_part_get_content_disposition (CamelMimePart *mime_part)
+{
+       g_return_val_if_fail (mime_part != NULL, NULL);
 
-       g_object_notify (G_OBJECT (mime_part), "description");
+       return mime_part->priv->disposition;
 }
 
 /**
- * camel_mime_part_get_description:
- * @mime_part: a #CamelMimePart object
+ * camel_mime_part_get_content_id:
+ * @mime_part: a #CamelMimePart
  *
- * Get the description of the MIME part.
+ * Get the content-id field of a MIME part.
  *
- * Returns: the description
+ * Returns: the content-id field of the MIME part
  **/
 const gchar *
-camel_mime_part_get_description (CamelMimePart *mime_part)
+camel_mime_part_get_content_id (CamelMimePart *mime_part)
 {
        g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), NULL);
 
-       return mime_part->priv->description;
+       return mime_part->priv->content_id;
 }
 
-/* **** Content-Disposition */
-
 /**
- * camel_mime_part_set_disposition:
- * @mime_part: a #CamelMimePart object
- * @disposition: disposition of the MIME part
+ * camel_mime_part_set_content_id:
+ * @mime_part: a #CamelMimePart
+ * @contentid: content id
  *
- * Set a disposition on the MIME part.
+ * Set the content-id field on a MIME part.
  **/
 void
-camel_mime_part_set_disposition (CamelMimePart *mime_part,
-                                 const gchar *disposition)
+camel_mime_part_set_content_id (CamelMimePart *mime_part,
+                                const gchar *contentid)
 {
        CamelMedium *medium;
-       gchar *text;
+       gchar *cid, *id;
 
        g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
 
        medium = CAMEL_MEDIUM (mime_part);
 
-       /* we poke in a new disposition (so we dont lose 'filename', etc) */
-       if (mime_part->priv->disposition == NULL)
-               mime_part_set_disposition (mime_part, disposition);
+       if (contentid)
+               id = g_strstrip (g_strdup (contentid));
+       else
+               id = camel_header_msgid_generate ();
 
-       if (mime_part->priv->disposition != NULL) {
-               g_free (mime_part->priv->disposition->disposition);
-               mime_part->priv->disposition->disposition = g_strdup (disposition);
-       }
+       cid = g_strdup_printf ("<%s>", id);
+       camel_medium_set_header (medium, "Content-ID", cid);
+       g_free (cid);
 
-       text = camel_content_disposition_format (mime_part->priv->disposition);
-       camel_medium_set_header (medium, "Content-Disposition", text);
-       g_free (text);
+       g_free (id);
 
-       g_object_notify (G_OBJECT (mime_part), "disposition");
+       g_object_notify (G_OBJECT (mime_part), "content-id");
 }
 
 /**
- * camel_mime_part_get_disposition:
- * @mime_part: a #CamelMimePart object
+ * camel_mime_part_get_content_location:
+ * @mime_part: a #CamelMimePart
  *
- * Get the disposition of the MIME part.
+ * Get the content-location field of a MIME part.
  *
- * Returns: the disposition
+ * Returns: the content-location field of a MIME part
  **/
 const gchar *
-camel_mime_part_get_disposition (CamelMimePart *mime_part)
+camel_mime_part_get_content_location (CamelMimePart *mime_part)
 {
        g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), NULL);
 
-       if (mime_part->priv->disposition)
-               return mime_part->priv->disposition->disposition;
-       else
-               return NULL;
+       return mime_part->priv->content_location;
 }
 
 /**
- * camel_mime_part_get_content_disposition:
- * @mime_part: a #CamelMimePart object
+ * camel_mime_part_set_content_location:
+ * @mime_part: a #CamelMimePart
+ * @location: the content-location value of the MIME part
  *
- * Get the disposition of the MIME part as a structure.
- * Returned pointer is owned by #mime_part.
+ * Set the content-location field of the MIME part.
+ **/
+void
+camel_mime_part_set_content_location (CamelMimePart *mime_part,
+                                      const gchar *location)
+{
+       CamelMedium *medium;
+
+       g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
+
+       medium = CAMEL_MEDIUM (mime_part);
+
+       /* FIXME: this should perform content-location folding */
+       camel_medium_set_header (medium, "Content-Location", location);
+
+       g_object_notify (G_OBJECT (mime_part), "content-location");
+}
+
+/**
+ * camel_mime_part_get_content_md5:
+ * @mime_part: a #CamelMimePart
  *
- * Returns: the disposition structure
+ * Get the content-md5 field of the MIME part.
  *
- * Since: 2.30
+ * Returns: the content-md5 field of the MIME part
  **/
-const CamelContentDisposition *
-camel_mime_part_get_content_disposition (CamelMimePart *mime_part)
+const gchar *
+camel_mime_part_get_content_md5 (CamelMimePart *mime_part)
 {
-       g_return_val_if_fail (mime_part != NULL, NULL);
+       g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), NULL);
 
-       return mime_part->priv->disposition;
+       return mime_part->priv->content_md5;
 }
 
-/* **** Content-Disposition: filename="xxx" */
-
 /**
- * camel_mime_part_set_filename:
- * @mime_part: a #CamelMimePart object
- * @filename: filename given to the MIME part
+ * camel_mime_part_set_content_md5:
+ * @mime_part: a #CamelMimePart
+ * @md5sum: the md5sum of the MIME part
  *
- * Set the filename on a MIME part.
+ * Set the content-md5 field of the MIME part.
  **/
 void
-camel_mime_part_set_filename (CamelMimePart *mime_part, const gchar *filename)
+camel_mime_part_set_content_md5 (CamelMimePart *mime_part,
+                                 const gchar *content_md5)
 {
-       CamelDataWrapper *dw;
        CamelMedium *medium;
-       gchar *str;
-
-       medium = CAMEL_MEDIUM (mime_part);
-
-       if (mime_part->priv->disposition == NULL)
-               mime_part->priv->disposition =
-                       camel_content_disposition_decode("attachment");
 
-       camel_header_set_param (
-               &mime_part->priv->disposition->params, "filename", filename);
-       str = camel_content_disposition_format (mime_part->priv->disposition);
+       g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
 
-       camel_medium_set_header (medium, "Content-Disposition", str);
-       g_free (str);
+       medium = CAMEL_MEDIUM (mime_part);
 
-       dw = (CamelDataWrapper *) mime_part;
-       if (!dw->mime_type)
-               dw->mime_type = camel_content_type_new ("application", "octet-stream");
-       camel_content_type_set_param (dw->mime_type, "name", filename);
-       str = camel_content_type_format (dw->mime_type);
-       camel_medium_set_header (medium, "Content-Type", str);
-       g_free (str);
+       camel_medium_set_header (medium, "Content-MD5", content_md5);
 }
 
 /**
- * camel_mime_part_get_filename:
- * @mime_part: a #CamelMimePart object
+ * camel_mime_part_get_content_languages:
+ * @mime_part: a #CamelMimePart
  *
- * Get the filename of a MIME part.
+ * Get the Content-Languages set on the MIME part.
  *
- * Returns: the filename of the MIME part
+ * Returns: a #GList of languages
  **/
-const gchar *
-camel_mime_part_get_filename (CamelMimePart *mime_part)
+const GList *
+camel_mime_part_get_content_languages (CamelMimePart *mime_part)
 {
-       if (mime_part->priv->disposition) {
-               const gchar *name = camel_header_param (
-                       mime_part->priv->disposition->params, "filename");
-               if (name)
-                       return name;
-       }
+       g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), NULL);
 
-       return camel_content_type_param (((CamelDataWrapper *) mime_part)->mime_type, "name");
+       return mime_part->priv->content_languages;
 }
 
-/* **** Content-ID: */
-
 /**
- * camel_mime_part_set_content_id:
- * @mime_part: a #CamelMimePart object
- * @contentid: content id
+ * camel_mime_part_set_content_languages:
+ * @mime_part: a #CamelMimePart
+ * @content_languages: list of languages
  *
- * Set the content-id field on a MIME part.
+ * Set the Content-Languages field of a MIME part.
  **/
 void
-camel_mime_part_set_content_id (CamelMimePart *mime_part,
-                                const gchar *contentid)
+camel_mime_part_set_content_languages (CamelMimePart *mime_part,
+                                       GList *content_languages)
 {
-       CamelMedium *medium;
-       gchar *cid, *id;
-
        g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
 
-       medium = CAMEL_MEDIUM (mime_part);
-
-       if (contentid)
-               id = g_strstrip (g_strdup (contentid));
-       else
-               id = camel_header_msgid_generate ();
-
-       cid = g_strdup_printf ("<%s>", id);
-       camel_medium_set_header (medium, "Content-ID", cid);
-       g_free (cid);
+       if (mime_part->priv->content_languages)
+               camel_string_list_free (mime_part->priv->content_languages);
 
-       g_free (id);
+       mime_part->priv->content_languages = content_languages;
 
-       g_object_notify (G_OBJECT (mime_part), "content-id");
+       /* FIXME: translate to a header and set it */
 }
 
 /**
- * camel_mime_part_get_content_id:
- * @mime_part: a #CamelMimePart object
+ * camel_mime_part_get_content_type:
+ * @mime_part: a #CamelMimePart
  *
- * Get the content-id field of a MIME part.
+ * Get the Content-Type of a MIME part.
  *
- * Returns: the content-id field of the MIME part
+ * Returns: the parsed #CamelContentType of the MIME part
  **/
-const gchar *
-camel_mime_part_get_content_id (CamelMimePart *mime_part)
+CamelContentType *
+camel_mime_part_get_content_type (CamelMimePart *mime_part)
 {
+       CamelDataWrapper *data_wrapper;
+
        g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), NULL);
 
-       return mime_part->priv->content_id;
-}
+       data_wrapper = CAMEL_DATA_WRAPPER (mime_part);
 
-/* **** Content-MD5: */
+       return camel_data_wrapper_get_mime_type_field (data_wrapper);
+}
 
 /**
- * camel_mime_part_set_content_md5:
- * @mime_part: a #CamelMimePart object
- * @md5sum: the md5sum of the MIME part
+ * camel_mime_part_set_content_type:
+ * @mime_part: a #CamelMimePart
+ * @content_type: content-type string
  *
- * Set the content-md5 field of the MIME part.
+ * Set the content-type on a MIME part.
  **/
 void
-camel_mime_part_set_content_md5 (CamelMimePart *mime_part,
-                                 const gchar *content_md5)
+camel_mime_part_set_content_type (CamelMimePart *mime_part,
+                                  const gchar *content_type)
 {
        CamelMedium *medium;
 
@@ -1088,93 +1188,107 @@ camel_mime_part_set_content_md5 (CamelMimePart *mime_part,
 
        medium = CAMEL_MEDIUM (mime_part);
 
-       camel_medium_set_header (medium, "Content-MD5", content_md5);
+       camel_medium_set_header (medium, "Content-Type", content_type);
 }
 
 /**
- * camel_mime_part_get_content_md5:
- * @mime_part: a #CamelMimePart object
+ * camel_mime_part_get_description:
+ * @mime_part: a #CamelMimePart
  *
- * Get the content-md5 field of the MIME part.
+ * Get the description of the MIME part.
  *
- * Returns: the content-md5 field of the MIME part
+ * Returns: the description
  **/
 const gchar *
-camel_mime_part_get_content_md5 (CamelMimePart *mime_part)
+camel_mime_part_get_description (CamelMimePart *mime_part)
 {
        g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), NULL);
 
-       return mime_part->priv->content_md5;
+       return mime_part->priv->description;
 }
 
-/* **** Content-Location: */
-
 /**
- * camel_mime_part_set_content_location:
- * @mime_part: a #CamelMimePart object
- * @location: the content-location value of the MIME part
+ * camel_mime_part_set_description:
+ * @mime_part: a #CamelMimePart
+ * @description: description of the MIME part
  *
- * Set the content-location field of the MIME part.
+ * Set a description on the MIME part.
  **/
 void
-camel_mime_part_set_content_location (CamelMimePart *mime_part,
-                                      const gchar *location)
+camel_mime_part_set_description (CamelMimePart *mime_part,
+                                 const gchar *description)
 {
        CamelMedium *medium;
+       gchar *text;
 
        g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
+       g_return_if_fail (description != NULL);
 
        medium = CAMEL_MEDIUM (mime_part);
 
-       /* FIXME: this should perform content-location folding */
-       camel_medium_set_header (medium, "Content-Location", location);
+       text = camel_header_encode_string ((guchar *) description);
+       camel_medium_set_header (medium, "Content-Description", text);
+       g_free (text);
 
-       g_object_notify (G_OBJECT (mime_part), "content-location");
+       g_object_notify (G_OBJECT (mime_part), "description");
 }
 
 /**
- * camel_mime_part_get_content_location:
- * @mime_part: a #CamelMimePart object
+ * camel_mime_part_get_disposition:
+ * @mime_part: a #CamelMimePart
  *
- * Get the content-location field of a MIME part.
+ * Get the disposition of the MIME part.
  *
- * Returns: the content-location field of a MIME part
+ * Returns: the disposition
  **/
 const gchar *
-camel_mime_part_get_content_location (CamelMimePart *mime_part)
+camel_mime_part_get_disposition (CamelMimePart *mime_part)
 {
        g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), NULL);
 
-       return mime_part->priv->content_location;
+       if (mime_part->priv->disposition)
+               return mime_part->priv->disposition->disposition;
+       else
+               return NULL;
 }
 
-/* **** Content-Transfer-Encoding: */
-
 /**
- * camel_mime_part_set_encoding:
- * @mime_part: a #CamelMimePart object
- * @encoding: a #CamelTransferEncoding
+ * camel_mime_part_set_disposition:
+ * @mime_part: a #CamelMimePart
+ * @disposition: disposition of the MIME part
  *
- * Set the Content-Transfer-Encoding to use on a MIME part.
+ * Set a disposition on the MIME part.
  **/
 void
-camel_mime_part_set_encoding (CamelMimePart *mime_part,
-                              CamelTransferEncoding encoding)
+camel_mime_part_set_disposition (CamelMimePart *mime_part,
+                                 const gchar *disposition)
 {
        CamelMedium *medium;
-       const gchar *text;
+       gchar *text;
 
        g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
 
        medium = CAMEL_MEDIUM (mime_part);
 
-       text = camel_transfer_encoding_to_string (encoding);
-       camel_medium_set_header (medium, "Content-Transfer-Encoding", text);
+       /* we poke in a new disposition (so we dont lose 'filename', etc) */
+       if (mime_part->priv->disposition == NULL)
+               mime_part_set_disposition (mime_part, disposition);
+
+       if (mime_part->priv->disposition != NULL) {
+               g_free (mime_part->priv->disposition->disposition);
+               mime_part->priv->disposition->disposition = g_strdup (disposition);
+       }
+
+       text = camel_content_disposition_format (mime_part->priv->disposition);
+       camel_medium_set_header (medium, "Content-Disposition", text);
+       g_free (text);
+
+       g_object_notify (G_OBJECT (mime_part), "disposition");
 }
 
 /**
  * camel_mime_part_get_encoding:
- * @mime_part: a #CamelMimePart object
+ * @mime_part: a #CamelMimePart
  *
  * Get the Content-Transfer-Encoding of a MIME part.
  *
@@ -1190,193 +1304,185 @@ camel_mime_part_get_encoding (CamelMimePart *mime_part)
        return mime_part->priv->encoding;
 }
 
-/* FIXME: do something with this stuff ... */
-
 /**
- * camel_mime_part_set_content_languages:
- * @mime_part: a #CamelMimePart object
- * @content_languages: list of languages
+ * camel_mime_part_set_encoding:
+ * @mime_part: a #CamelMimePart
+ * @encoding: a #CamelTransferEncoding
  *
- * Set the Content-Languages field of a MIME part.
+ * Set the Content-Transfer-Encoding to use on a MIME part.
  **/
 void
-camel_mime_part_set_content_languages (CamelMimePart *mime_part,
-                                       GList *content_languages)
+camel_mime_part_set_encoding (CamelMimePart *mime_part,
+                              CamelTransferEncoding encoding)
 {
-       g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
+       CamelMedium *medium;
+       const gchar *text;
 
-       if (mime_part->priv->content_languages)
-               camel_string_list_free (mime_part->priv->content_languages);
+       g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
 
-       mime_part->priv->content_languages = content_languages;
+       medium = CAMEL_MEDIUM (mime_part);
 
-       /* FIXME: translate to a header and set it */
+       text = camel_transfer_encoding_to_string (encoding);
+       camel_medium_set_header (medium, "Content-Transfer-Encoding", text);
 }
 
 /**
- * camel_mime_part_get_content_languages:
- * @mime_part: a #CamelMimePart object
+ * camel_mime_part_get_filename:
+ * @mime_part: a #CamelMimePart
  *
- * Get the Content-Languages set on the MIME part.
+ * Get the filename of a MIME part.
  *
- * Returns: a #GList of languages
+ * Returns: the filename of the MIME part
  **/
-const GList *
-camel_mime_part_get_content_languages (CamelMimePart *mime_part)
+const gchar *
+camel_mime_part_get_filename (CamelMimePart *mime_part)
 {
-       g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), NULL);
+       if (mime_part->priv->disposition) {
+               const gchar *name = camel_header_param (
+                       mime_part->priv->disposition->params, "filename");
+               if (name)
+                       return name;
+       }
 
-       return mime_part->priv->content_languages;
+       return camel_content_type_param (
+               ((CamelDataWrapper *) mime_part)->mime_type, "name");
 }
 
-/* **** */
-
-/* **** Content-Type: */
-
 /**
- * camel_mime_part_set_content_type:
- * @mime_part: a #CamelMimePart object
- * @content_type: content-type string
+ * camel_mime_part_set_filename:
+ * @mime_part: a #CamelMimePart
+ * @filename: filename given to the MIME part
  *
- * Set the content-type on a MIME part.
+ * Set the filename on a MIME part.
  **/
 void
-camel_mime_part_set_content_type (CamelMimePart *mime_part,
-                                  const gchar *content_type)
+camel_mime_part_set_filename (CamelMimePart *mime_part,
+                              const gchar *filename)
 {
+       CamelDataWrapper *dw;
        CamelMedium *medium;
-
-       g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
+       gchar *str;
 
        medium = CAMEL_MEDIUM (mime_part);
 
-       camel_medium_set_header (medium, "Content-Type", content_type);
-}
+       if (mime_part->priv->disposition == NULL)
+               mime_part->priv->disposition =
+                       camel_content_disposition_decode("attachment");
 
-/**
- * camel_mime_part_get_content_type:
- * @mime_part: a #CamelMimePart object
- *
- * Get the Content-Type of a MIME part.
- *
- * Returns: the parsed #CamelContentType of the MIME part
- **/
-CamelContentType *
-camel_mime_part_get_content_type (CamelMimePart *mime_part)
-{
-       g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), NULL);
+       camel_header_set_param (
+               &mime_part->priv->disposition->params, "filename", filename);
+       str = camel_content_disposition_format (mime_part->priv->disposition);
+
+       camel_medium_set_header (medium, "Content-Disposition", str);
+       g_free (str);
 
-       return camel_data_wrapper_get_mime_type_field ((CamelDataWrapper *) mime_part);
+       dw = (CamelDataWrapper *) mime_part;
+       if (!dw->mime_type)
+               dw->mime_type = camel_content_type_new ("application", "octet-stream");
+       camel_content_type_set_param (dw->mime_type, "name", filename);
+       str = camel_content_type_format (dw->mime_type);
+       camel_medium_set_header (medium, "Content-Type", str);
+       g_free (str);
 }
 
 /**
  * camel_mime_part_construct_from_parser_sync:
- * @mime_part: a #CamelMimePart object
- * @parser: a #CamelMimeParser object
+ * @mime_part: a #CamelMimePart
+ * @parser: a #CamelMimeParser
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Constructs a MIME part from a parser.
  *
- * Returns: %0 on success or %-1 on fail
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
-gint
+gboolean
 camel_mime_part_construct_from_parser_sync (CamelMimePart *mime_part,
-                                            CamelMimeParser *mp,
+                                            CamelMimeParser *parser,
                                             GCancellable *cancellable,
                                             GError **error)
 {
        CamelMimePartClass *class;
-       gint retval;
+       gboolean success;
 
        g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), -1);
-       g_return_val_if_fail (CAMEL_IS_MIME_PARSER (mp), -1);
+       g_return_val_if_fail (CAMEL_IS_MIME_PARSER (parser), -1);
 
        class = CAMEL_MIME_PART_GET_CLASS (mime_part);
        g_return_val_if_fail (class->construct_from_parser_sync != NULL, -1);
 
-       retval = class->construct_from_parser_sync (
-               mime_part, mp, cancellable, error);
+       success = class->construct_from_parser_sync (
+               mime_part, parser, cancellable, error);
        CAMEL_CHECK_GERROR (
-               mime_part, construct_from_parser_sync, retval == 0, error);
+               mime_part, construct_from_parser_sync, success, error);
 
-       return retval;
+       return success;
 }
 
 /**
- * camel_mime_part_new:
+ * camel_mime_part_construct_from_parser:
+ * @mime_part: a #CamelMimePart
+ * @parser: a #CamelMimeParser
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
  *
- * Create a new MIME part.
+ * Asynchronously constructs a MIME part from a parser.
  *
- * Returns: a new #CamelMimePart object
- **/
-CamelMimePart *
-camel_mime_part_new (void)
-{
-       return g_object_new (CAMEL_TYPE_MIME_PART, NULL);
-}
-
-/**
- * camel_mime_part_set_content:
- * @mime_part: a #CamelMimePart object
- * @data: data to put into the part
- * @length: length of @data
- * @type: Content-Type of the data
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_mime_part_construct_from_parser_finish() to get the result of
+ * the operation.
  *
- * Utility function used to set the content of a mime part object to
- * be the provided data. If @length is 0, this routine can be used as
- * a way to remove old content (in which case @data and @type are
- * ignored and may be %NULL).
+ * Since: 2.34
  **/
 void
-camel_mime_part_set_content (CamelMimePart *mime_part,
-                            const gchar *data, gint length,
-                            const gchar *type) /* why on earth is the type last? */
+camel_mime_part_construct_from_parser (CamelMimePart *mime_part,
+                                       CamelMimeParser *parser,
+                                       gint io_priority,
+                                       GCancellable *cancellable,
+                                       GAsyncReadyCallback callback,
+                                       gpointer user_data)
 {
-       CamelMedium *medium = CAMEL_MEDIUM (mime_part);
+       CamelMimePartClass *class;
 
-       if (length) {
-               CamelDataWrapper *dw;
-               CamelStream *stream;
+       g_return_if_fail (CAMEL_IS_MIME_PART (mime_part));
+       g_return_if_fail (CAMEL_IS_MIME_PARSER (parser));
 
-               dw = camel_data_wrapper_new ();
-               camel_data_wrapper_set_mime_type (dw, type);
-               stream = camel_stream_mem_new_with_buffer (data, length);
-               camel_data_wrapper_construct_from_stream_sync (
-                       dw, stream, NULL, NULL);
-               g_object_unref (stream);
-               camel_medium_set_content (medium, dw);
-               g_object_unref (dw);
-       } else
-               camel_medium_set_content (medium, NULL);
+       class = CAMEL_MIME_PART_GET_CLASS (mime_part);
+       g_return_if_fail (class->construct_from_parser != NULL);
+
+       class->construct_from_parser (
+               mime_part, parser, io_priority,
+               cancellable, callback, user_data);
 }
 
 /**
- * camel_mime_part_get_content_size:
- * @mime_part: a #CamelMimePart object
+ * camel_mime_part_construct_from_parser_finish:
+ * @mime_part: a #CamelMimePart
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
  *
- * Get the decoded size of the MIME part's content.
+ * Finishes the operation started with camel_mime_part_construct_from_parser().
  *
- * Returns: the size of the MIME part's content in bytes.
+ * Returns: %TRUE on success, %FALSE on error
  *
- * Since: 2.22
+ * Since: 2.34
  **/
-gsize
-camel_mime_part_get_content_size (CamelMimePart *mime_part)
+gboolean
+camel_mime_part_construct_from_parser_finish (CamelMimePart *mime_part,
+                                              GAsyncResult *result,
+                                              GError **error)
 {
-       CamelStream *null;
-       CamelDataWrapper *dw;
-       gsize size;
-
-       g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), 0);
-
-       dw = camel_medium_get_content (CAMEL_MEDIUM (mime_part));
+       CamelMimePartClass *class;
 
-       null = camel_stream_null_new ();
-       camel_data_wrapper_decode_to_stream_sync (dw, null, NULL, NULL);
-       size = CAMEL_STREAM_NULL (null)->written;
+       g_return_val_if_fail (CAMEL_IS_MIME_PART (mime_part), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
 
-       g_object_unref (null);
+       class = CAMEL_MIME_PART_GET_CLASS (mime_part);
+       g_return_val_if_fail (class->construct_from_parser_finish != NULL, FALSE);
 
-       return size;
+       return class->construct_from_parser_finish (mime_part, result, error);
 }
index 748a31b..89b0dc1 100644 (file)
@@ -69,10 +69,25 @@ struct _CamelMimePart {
 struct _CamelMimePartClass {
        CamelMediumClass parent_class;
 
-       gint    (*construct_from_parser_sync)   (CamelMimePart *mime_part,
+       /* Synchronous I/O Methods */
+       gboolean        (*construct_from_parser_sync)
+                                               (CamelMimePart *mime_part,
                                                 CamelMimeParser *parser,
                                                 GCancellable *cancellable,
                                                 GError **error);
+
+       /* Asynchronous I/O Methods (all have defaults) */
+       void            (*construct_from_parser)
+                                               (CamelMimePart *mime_part,
+                                                CamelMimeParser *parser,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*construct_from_parser_finish)
+                                               (CamelMimePart *mime_part,
+                                                GAsyncResult *result,
+                                                GError **error);
 };
 
 GType          camel_mime_part_get_type        (void);
@@ -119,13 +134,23 @@ void              camel_mime_part_set_content     (CamelMimePart *mime_part,
                                                 const gchar *data,
                                                 gint length,
                                                 const gchar *type);
-gsize          camel_mime_part_get_content_size
-                                               (CamelMimePart *mime_part);
-gint           camel_mime_part_construct_from_parser_sync
+
+gboolean       camel_mime_part_construct_from_parser_sync
                                                (CamelMimePart *mime_part,
                                                 CamelMimeParser *parser,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_mime_part_construct_from_parser
+                                               (CamelMimePart *mime_part,
+                                                CamelMimeParser *parser,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_mime_part_construct_from_parser_finish
+                                               (CamelMimePart *mime_part,
+                                                GAsyncResult *result,
+                                                GError **error);
 
 G_END_DECLS
 
index 21968fb..1affe87 100644 (file)
@@ -359,7 +359,7 @@ file_error:
        return -1;
 }
 
-static gint
+static gboolean
 multipart_signed_construct_from_stream_sync (CamelDataWrapper *data_wrapper,
                                              CamelStream *stream,
                                              GCancellable *cancellable,
@@ -370,11 +370,11 @@ multipart_signed_construct_from_stream_sync (CamelDataWrapper *data_wrapper,
 
        if (camel_stream_write_to_stream (
                stream, mem, cancellable, error) == -1)
-               return -1;
+               return FALSE;
 
        multipart_signed_set_stream (mps, mem);
 
-       return 0;
+       return TRUE;
 }
 
 static void
index 6769285..13d3b97 100644 (file)
@@ -691,7 +691,7 @@ camel_getaddrinfo (const gchar *name,
        if (g_cancellable_set_error_if_cancelled (cancellable, error))
                return NULL;
 
-       camel_operation_start_transient (
+       camel_operation_push_message (
                cancellable, _("Resolving: %s"), name);
 
        /* force ipv4 addresses only */
@@ -729,7 +729,7 @@ camel_getaddrinfo (const gchar *name,
 
        cs_freeinfo (msg);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return res;
 }
@@ -841,7 +841,7 @@ camel_getnameinfo (const struct sockaddr *sa,
        if (g_cancellable_set_error_if_cancelled (cancellable, error))
                return -1;
 
-       camel_operation_start_transient (
+       camel_operation_push_message (
                cancellable, _("Resolving address"));
 
        msg = g_malloc0 (sizeof (*msg));
@@ -879,7 +879,7 @@ camel_getnameinfo (const struct sockaddr *sa,
 
        cs_freeinfo (msg);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return result;
 }
index 73338f6..7e755d2 100644 (file)
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), CAMEL_TYPE_OFFLINE_FOLDER, CamelOfflineFolderPrivate))
 
+typedef struct _AsyncContext AsyncContext;
+
 struct _CamelOfflineFolderPrivate {
        gboolean offline_sync;
 };
 
+struct _AsyncContext {
+       /* arguments */
+       gchar *expression;
+};
+
 struct _offline_downsync_msg {
        CamelSessionThreadMsg msg;
 
@@ -58,12 +65,20 @@ enum {
 G_DEFINE_TYPE (CamelOfflineFolder, camel_offline_folder, CAMEL_TYPE_FOLDER)
 
 static void
+async_context_free (AsyncContext *async_context)
+{
+       g_free (async_context->expression);
+
+       g_slice_free (AsyncContext, async_context);
+}
+
+static void
 offline_downsync_sync (CamelSession *session, CamelSessionThreadMsg *mm)
 {
        struct _offline_downsync_msg *m = (struct _offline_downsync_msg *) mm;
        gint i;
 
-       camel_operation_start (
+       camel_operation_push_message (
                mm->cancellable,
                _("Downloading new messages for offline mode"));
 
@@ -84,7 +99,7 @@ offline_downsync_sync (CamelSession *session, CamelSessionThreadMsg *mm)
                        "(match-all)", NULL, &mm->error);
        }
 
-       camel_operation_end (mm->cancellable);
+       camel_operation_pop_message (mm->cancellable);
 }
 
 static void
@@ -174,7 +189,7 @@ offline_folder_downsync_sync (CamelOfflineFolder *offline,
        GPtrArray *uids, *uncached_uids = NULL;
        gint i;
 
-       camel_operation_start (
+       camel_operation_push_message (
                cancellable, _("Syncing messages in folder '%s' to disk"),
                camel_folder_get_full_name (folder));
 
@@ -207,12 +222,77 @@ done:
        if (uncached_uids)
                camel_folder_free_uids (folder, uncached_uids);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return TRUE;
 }
 
 static void
+offline_folder_downsync_thread (GSimpleAsyncResult *simple,
+                                GObject *object,
+                                GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_offline_folder_downsync_sync (
+               CAMEL_OFFLINE_FOLDER (object), async_context->expression,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+offline_folder_downsync (CamelOfflineFolder *folder,
+                         const gchar *expression,
+                         gint io_priority,
+                         GCancellable *cancellable,
+                         GAsyncReadyCallback callback,
+                         gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->expression = g_strdup (expression);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (folder), callback,
+               user_data, offline_folder_downsync);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, offline_folder_downsync_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+offline_folder_downsync_finish (CamelOfflineFolder *folder,
+                                GAsyncResult *result,
+                                GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (folder), offline_folder_downsync), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
 camel_offline_folder_class_init (CamelOfflineFolderClass *class)
 {
        GObjectClass *object_class;
@@ -224,6 +304,8 @@ camel_offline_folder_class_init (CamelOfflineFolderClass *class)
        object_class->get_property = offline_folder_get_property;
 
        class->downsync_sync = offline_folder_downsync_sync;
+       class->downsync = offline_folder_downsync;
+       class->downsync_finish = offline_folder_downsync_finish;
 
        g_object_class_install_property (
                object_class,
@@ -249,51 +331,53 @@ camel_offline_folder_init (CamelOfflineFolder *folder)
 
 /**
  * camel_offline_folder_get_offline_sync:
- * @offline_folder: a #CamelOfflineFolder
+ * @folder: a #CamelOfflineFolder
  *
  * Since: 2.32
  **/
 gboolean
-camel_offline_folder_get_offline_sync (CamelOfflineFolder *offline_folder)
+camel_offline_folder_get_offline_sync (CamelOfflineFolder *folder)
 {
-       g_return_val_if_fail (CAMEL_IS_OFFLINE_FOLDER (offline_folder), FALSE);
+       g_return_val_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder), FALSE);
 
-       return offline_folder->priv->offline_sync;
+       return folder->priv->offline_sync;
 }
 
 /**
  * camel_offline_folder_set_offline_sync:
- * @offline_folder: a #CamelOfflineFolder
+ * @folder: a #CamelOfflineFolder
  * @offline_sync: whether to synchronize for offline use
  *
  * Since: 2.32
  **/
 void
-camel_offline_folder_set_offline_sync (CamelOfflineFolder *offline_folder,
+camel_offline_folder_set_offline_sync (CamelOfflineFolder *folder,
                                        gboolean offline_sync)
 {
-       g_return_if_fail (CAMEL_IS_OFFLINE_FOLDER (offline_folder));
+       g_return_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder));
 
-       offline_folder->priv->offline_sync = offline_sync;
+       folder->priv->offline_sync = offline_sync;
 
-       g_object_notify (G_OBJECT (offline_folder), "offline-sync");
+       g_object_notify (G_OBJECT (folder), "offline-sync");
 }
 
 /**
  * camel_offline_folder_downsync_sync:
- * @offline: a #CamelOfflineFolder object
+ * @folder: a #CamelOfflineFolder
  * @expression: search expression describing which set of messages
  *              to downsync (%NULL for all)
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
- * Syncs messages in @offline described by the search @expression to
+ * Synchronizes messages in @folder described by the search @expression to
  * the local machine for offline availability.
  *
- * Returns: %TRUE on success, %FALSE on failure
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
 gboolean
-camel_offline_folder_downsync_sync (CamelOfflineFolder *offline,
+camel_offline_folder_downsync_sync (CamelOfflineFolder *folder,
                                     const gchar *expression,
                                     GCancellable *cancellable,
                                     GError **error)
@@ -301,14 +385,81 @@ camel_offline_folder_downsync_sync (CamelOfflineFolder *offline,
        CamelOfflineFolderClass *class;
        gboolean success;
 
-       g_return_val_if_fail (CAMEL_IS_OFFLINE_FOLDER (offline), FALSE);
+       g_return_val_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder), FALSE);
 
-       class = CAMEL_OFFLINE_FOLDER_GET_CLASS (offline);
+       class = CAMEL_OFFLINE_FOLDER_GET_CLASS (folder);
        g_return_val_if_fail (class->downsync_sync != NULL, FALSE);
 
        success = class->downsync_sync (
-               offline, expression, cancellable, error);
-       CAMEL_CHECK_GERROR (offline, downsync_sync, success, error);
+               folder, expression, cancellable, error);
+       CAMEL_CHECK_GERROR (folder, downsync_sync, success, error);
 
        return success;
 }
+
+/**
+ * camel_offline_folder_downsync:
+ * @folder: a #CamelOfflineFolder
+ * @expression: search expression describing which set of messages
+ *              to downsync (%NULL for all)
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULl
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Synchronizes messages in @folder described by the search @expression to
+ * the local machine asynchronously for offline availability.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_offline_folder_downsync_finish() to get the result of the
+ * operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_offline_folder_downsync (CamelOfflineFolder *folder,
+                               const gchar *expression,
+                               gint io_priority,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
+{
+       CamelOfflineFolderClass *class;
+
+       g_return_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder));
+
+       class = CAMEL_OFFLINE_FOLDER_GET_CLASS (folder);
+       g_return_if_fail (class->downsync != NULL);
+
+       class->downsync (
+               folder, expression, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_offline_folder_downsync_finish:
+ * @folder: a #CamelOfflineFolder
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_offline_folder_downsync().
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_offline_folder_downsync_finish (CamelOfflineFolder *folder,
+                                      GAsyncResult *result,
+                                      GError **error)
+{
+       CamelOfflineFolderClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_OFFLINE_FOLDER (folder), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_OFFLINE_FOLDER_GET_CLASS (folder);
+       g_return_val_if_fail (class->downsync_finish != NULL, FALSE);
+
+       return class->downsync_finish (folder, result, error);
+}
index d3ca48c..977e769 100644 (file)
@@ -62,22 +62,45 @@ struct _CamelOfflineFolder {
 struct _CamelOfflineFolderClass {
        CamelFolderClass parent_class;
 
+       /* Synchronous I/O Methods */
        gboolean        (*downsync_sync)        (CamelOfflineFolder *folder,
                                                 const gchar *expression,
                                                 GCancellable *cancellable,
                                                 GError **error);
+
+       /* Asynchronous I/O Methods (all have defaults) */
+       void            (*downsync)             (CamelOfflineFolder *folder,
+                                                const gchar *expression,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*downsync_finish)      (CamelOfflineFolder *folder,
+                                                GAsyncResult *result,
+                                                GError **error);
 };
 
 GType          camel_offline_folder_get_type   (void);
 gboolean       camel_offline_folder_get_offline_sync
-                                               (CamelOfflineFolder *offline);
+                                               (CamelOfflineFolder *folder);
 void           camel_offline_folder_set_offline_sync
-                                               (CamelOfflineFolder *offline,
+                                               (CamelOfflineFolder *folder,
                                                 gboolean offline_sync);
+
 gboolean       camel_offline_folder_downsync_sync
-                                               (CamelOfflineFolder *offline,
+                                               (CamelOfflineFolder *folder,
+                                                const gchar *expression,
+                                                GCancellable *cancellable,
+                                                GError **error);
+void           camel_offline_folder_downsync   (CamelOfflineFolder *folder,
                                                 const gchar *expression,
+                                                gint io_priority,
                                                 GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_offline_folder_downsync_finish
+                                               (CamelOfflineFolder *folder,
+                                                GAsyncResult *result,
                                                 GError **error);
 
 G_END_DECLS
index 82c6989..f00c92b 100644 (file)
 typedef struct _StatusNode StatusNode;
 
 struct _StatusNode {
-       gboolean transient;
-       gchar *msg;
-       gint pc;                /* last percentage reported */
-       guint stamp;            /* last time stamp reported */
+       CamelOperation *operation;
+       guint source_id;  /* for timeout or idle */
+       gchar *message;
+       gint percent;
 };
 
 struct _CamelOperationPrivate {
-       guint status_idle_id;
-
-       /* For the next 'status' signal. */
-       gchar *status_msg;
-       gint status_pc;
-
-       guint status_update;
 
        GQueue status_stack;
 
@@ -66,9 +59,6 @@ enum {
        LAST_SIGNAL
 };
 
-/* Delay before a transient operation has any effect on the status */
-#define CAMEL_OPERATION_TRANSIENT_DELAY (5)
-
 static GStaticRecMutex operation_lock = G_STATIC_REC_MUTEX_INIT;
 #define LOCK() g_static_rec_mutex_lock (&operation_lock)
 #define UNLOCK() g_static_rec_mutex_unlock (&operation_lock)
@@ -79,85 +69,56 @@ static guint signals[LAST_SIGNAL];
 
 G_DEFINE_TYPE (CamelOperation, camel_operation, G_TYPE_CANCELLABLE)
 
-static StatusNode *
-status_node_new (CamelOperation *operation)
-{
-       StatusNode *node;
-
-       node = g_slice_new0 (StatusNode);
-       g_queue_push_head (&operation->priv->status_stack, node);
-
-       return node;
-}
-
 static void
 status_node_free (StatusNode *node)
 {
-       g_free (node->msg);
-       g_slice_free (StatusNode, node);
-}
+       g_free (node->message);
 
-static guint
-stamp (void)
-{
-       GTimeVal tv;
+       if (node->source_id > 0)
+               g_source_remove (node->source_id);
 
-       g_get_current_time (&tv);
-       /* update 4 times/second */
-       return (tv.tv_sec * 4) + tv.tv_usec / (1000000/4);
+       g_slice_free (StatusNode, node);
 }
 
 static gboolean
-operation_idle_cb (CamelOperation *operation)
+operation_emit_status_cb (StatusNode *node)
 {
-       gchar *msg;
-       gint pc;
+       StatusNode *head_node;
+       gchar *message = NULL;
+       gint percent = 0;
 
        /* Keep the operation alive until we emit the signal,
         * otherwise it might be finalized between unlocking
         * the mutex and emitting the signal. */
-       g_object_ref (operation);
+       g_object_ref (node->operation);
 
        LOCK ();
 
-       msg = operation->priv->status_msg;
-       operation->priv->status_msg = NULL;
+       node->source_id = 0;
 
-       pc = operation->priv->status_pc;
+       head_node = g_queue_peek_head (&node->operation->priv->status_stack);
 
-       operation->priv->status_idle_id = 0;
+       if (node == head_node) {
+               message = g_strdup (node->message);
+               percent = node->percent;
+       }
 
        UNLOCK ();
 
-       if (msg != NULL) {
-               g_signal_emit (operation, signals[STATUS], 0, msg, pc);
-               g_free (msg);
+       if (message != NULL) {
+               g_signal_emit (
+                       node->operation,
+                       signals[STATUS], 0,
+                       message, percent);
+               g_free (message);
        }
 
-       g_object_unref (operation);
+       g_object_unref (node->operation);
 
        return FALSE;
 }
 
 static void
-operation_queue_status_update (CamelOperation *operation,
-                               StatusNode *node)
-{
-       LOCK ();
-
-       if (operation->priv->status_idle_id == 0)
-               operation->priv->status_idle_id = g_idle_add (
-                       (GSourceFunc) operation_idle_cb, operation);
-
-       g_free (operation->priv->status_msg);
-       operation->priv->status_msg = g_strdup (node->msg);
-
-       operation->priv->status_pc = node->pc;
-
-       UNLOCK ();
-}
-
-static void
 operation_flush_msgport (CamelOperation *operation)
 {
        CamelOperationPrivate *priv = operation->priv;
@@ -183,16 +144,13 @@ operation_finalize (GObject *object)
 
        g_queue_remove (&operation_list, object);
 
-       if (priv->status_idle_id > 0)
-               g_source_remove (priv->status_idle_id);
-
        operation_flush_msgport (CAMEL_OPERATION (object));
        camel_msgport_destroy (priv->cancel_port);
 
        while ((node = g_queue_pop_head (&priv->status_stack)) != NULL) {
                g_warning (
                        "CamelOperation status stack non-empty: %s",
-                       node->msg);
+                       node->message);
                status_node_free (node);
        }
 
@@ -398,24 +356,24 @@ camel_operation_cancel_prfd (CamelOperation *operation)
 #endif /* CAMEL_HAVE_NSS */
 
 /**
- * camel_operation_start:
+ * camel_operation_push_message:
  * @cancellable: a #GCancellable or %NULL
- * @what: action being performed (printf-style format string)
- * @Varargs: varargs
+ * @format: a standard printf() format string
+ * @Varargs: the parameters to insert into the format string
  *
- * Report the start of an operation.  All start operations should have
- * similar end operations.
+ * Call this function to describe an operation being performed.
+ * Call camel_operation_progress() to report progress on the operation.
+ * Call camel_operation_pop_message() when the operation is complete.
  *
  * This function only works if @cancellable is a #CamelOperation cast as a
  * #GCancellable.  If @cancellable is a plain #GCancellable or %NULL, the
  * function does nothing and returns silently.
  **/
 void
-camel_operation_start (GCancellable *cancellable,
-                       const gchar *what, ...)
+camel_operation_push_message (GCancellable *cancellable,
+                              const gchar *format, ...)
 {
        CamelOperation *operation;
-       const guint signal_id = signals[STATUS];
        StatusNode *node;
        va_list ap;
 
@@ -427,48 +385,45 @@ camel_operation_start (GCancellable *cancellable,
 
        g_return_if_fail (CAMEL_IS_OPERATION (cancellable));
 
-       if (!g_signal_has_handler_pending (cancellable, signal_id, 0, TRUE))
-               return;
-
        LOCK ();
 
        operation = CAMEL_OPERATION (cancellable);
 
-       operation->priv->status_update = 0;
+       va_start (ap, format);
 
-       va_start (ap, what);
+       node = g_slice_new0 (StatusNode);
+       node->message = g_strdup_vprintf (format, ap);
+       node->operation = operation;  /* not referenced */
 
-       node = status_node_new (operation);
-       node->msg = g_strdup_vprintf (what, ap);
+       if (g_queue_is_empty (&operation->priv->status_stack))
+               node->source_id = g_idle_add (
+                       (GSourceFunc) operation_emit_status_cb, node);
+       else
+               node->source_id = g_timeout_add_seconds (
+                       4, (GSourceFunc) operation_emit_status_cb, node);
 
-       va_end (ap);
+       g_queue_push_head (&operation->priv->status_stack, node);
 
-       operation_queue_status_update (operation, node);
+       va_end (ap);
 
        UNLOCK ();
 }
 
 /**
- * camel_operation_start_transient:
- * @cancellable: a #GCancellable or %NULL
- * @what: printf-style format string describing the action being performed
- * @Varargs: varargs
+ * camel_operation_pop_message:
+ * @cancellable: a #GCancellable
  *
- * Start a transient event.  We only update this to the display if it
- * takes very long to process, and if we do, we then go back to the
- * previous state when finished.
+ * Pops the most recently pushed message.
  *
  * This function only works if @cancellable is a #CamelOperation cast as a
  * #GCancellable.  If @cancellable is a plain #GCancellable or %NULL, the
  * function does nothing and returns silently.
  **/
 void
-camel_operation_start_transient (GCancellable *cancellable,
-                                 const gchar *what, ...)
+camel_operation_pop_message (GCancellable *cancellable)
 {
        CamelOperation *operation;
        StatusNode *node;
-       va_list ap;
 
        if (cancellable == NULL)
                return;
@@ -481,17 +436,16 @@ camel_operation_start_transient (GCancellable *cancellable,
        LOCK ();
 
        operation = CAMEL_OPERATION (cancellable);
+       node = g_queue_pop_head (&operation->priv->status_stack);
 
-       operation->priv->status_update = 0;
+       if (node != NULL)
+               status_node_free (node);
 
-       va_start (ap, what);
+       node = g_queue_peek_head (&operation->priv->status_stack);
 
-       node = status_node_new (operation);
-       node->msg = g_strdup_vprintf (what, ap);
-       node->stamp = stamp ();
-       node->transient = TRUE;
-
-       va_end (ap);
+       if (node != NULL && node->source_id == 0)
+               node->source_id = g_idle_add (
+                       (GSourceFunc) operation_emit_status_cb, node);
 
        UNLOCK ();
 }
@@ -499,9 +453,9 @@ camel_operation_start_transient (GCancellable *cancellable,
 /**
  * camel_operation_progress:
  * @cancellable: a #GCancellable or %NULL
- * @pc: percent complete, 0 to 100.
+ * @percent: percent complete, 0 to 100.
  *
- * Report progress on the current operation.  @pc reports the current
+ * Report progress on the current operation.  @percent reports the current
  * percentage of completion, which should be in the range of 0 to 100.
  *
  * This function only works if @cancellable is a #CamelOperation cast as a
@@ -510,12 +464,9 @@ camel_operation_start_transient (GCancellable *cancellable,
  **/
 void
 camel_operation_progress (GCancellable *cancellable,
-                          gint pc)
+                          gint percent)
 {
        CamelOperation *operation;
-       const guint signal_id = signals[STATUS];
-       CamelOperationPrivate *priv;
-       guint now;
        StatusNode *node;
 
        if (cancellable == NULL)
@@ -526,83 +477,21 @@ camel_operation_progress (GCancellable *cancellable,
 
        g_return_if_fail (CAMEL_IS_OPERATION (cancellable));
 
-       if (!g_signal_has_handler_pending (cancellable, signal_id, 0, TRUE))
-               return;
-
        LOCK ();
 
        operation = CAMEL_OPERATION (cancellable);
-       priv = operation->priv;
+       node = g_queue_peek_head (&operation->priv->status_stack);
 
-       if (g_queue_is_empty (&priv->status_stack)) {
-               UNLOCK ();
-               return;
-       }
+       if (node != NULL) {
+               node->percent = percent;
 
-       node = g_queue_peek_head (&priv->status_stack);
-       node->pc = pc;
-
-       /* Transient messages dont start updating till 4 seconds after
-          they started, then they update every second */
-       now = stamp ();
-       if (priv->status_update == now) {
-               operation = NULL;
-       } else if (node->transient) {
-               if (node->stamp + CAMEL_OPERATION_TRANSIENT_DELAY > now) {
-                       operation = NULL;
-               } else {
-                       priv->status_update = now;
-               }
-       } else {
-               node->stamp = priv->status_update = now;
+               /* Rate limit progress updates. */
+               if (node->source_id == 0)
+                       node->source_id = g_timeout_add (
+                               250, (GSourceFunc)
+                               operation_emit_status_cb, node);
        }
 
-       if (operation != NULL)
-               operation_queue_status_update (operation, node);
-
        UNLOCK ();
 }
 
-/**
- * camel_operation_end:
- * @cancellable: a #GCancellable
- *
- * Report the end of an operation.
- *
- * This function only works if @cancellable is a #CamelOperation cast as a
- * #GCancellable.  If @cancellable is a plain #GCancellable or %NULL, the
- * function does nothing and returns silently.
- **/
-void
-camel_operation_end (GCancellable *cancellable)
-{
-       CamelOperation *operation;
-       const guint signal_id = signals[STATUS];
-       GQueue *status_stack;
-       StatusNode *node;
-
-       if (cancellable == NULL)
-               return;
-
-       if (G_OBJECT_TYPE (cancellable) == G_TYPE_CANCELLABLE)
-               return;
-
-       g_return_if_fail (CAMEL_IS_OPERATION (cancellable));
-
-       if (!g_signal_has_handler_pending (cancellable, signal_id, 0, TRUE))
-               return;
-
-       LOCK ();
-
-       operation = CAMEL_OPERATION (cancellable);
-
-       status_stack = &operation->priv->status_stack;
-
-       if ((node = g_queue_pop_head (status_stack)) != NULL) {
-               node->pc = 100;
-               operation_queue_status_update (operation, node);
-               status_node_free (node);
-       }
-
-       UNLOCK ();
-}
index 6b6b549..7cdec8e 100644 (file)
@@ -84,15 +84,12 @@ struct PRFileDesc *
  * a GCancellable pointer and just return silently if the pointer is
  * NULL or the pointed to object actually is a plain GCancellable. */
 
-void           camel_operation_start           (GCancellable *cancellable,
-                                                const gchar *what,
-                                                ...) G_GNUC_PRINTF (2, 3);
-void           camel_operation_start_transient (GCancellable *cancellable,
-                                                const gchar *what,
+void           camel_operation_push_message    (GCancellable *cancellable,
+                                                const gchar *format,
                                                 ...) G_GNUC_PRINTF (2, 3);
+void           camel_operation_pop_message     (GCancellable *cancellable);
 void           camel_operation_progress        (GCancellable *cancellable,
-                                                gint pc);
-void           camel_operation_end             (GCancellable *cancellable);
+                                                gint percent);
 
 G_END_DECLS
 
index 4966602..de82c55 100644 (file)
@@ -44,6 +44,8 @@
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), CAMEL_TYPE_SASL, CamelSaslPrivate))
 
+typedef struct _AsyncContext AsyncContext;
+
 struct _CamelSaslPrivate {
        CamelService *service;
        gboolean authenticated;
@@ -51,6 +53,16 @@ struct _CamelSaslPrivate {
        gchar *mechanism;
 };
 
+struct _AsyncContext {
+       /* arguments */
+       GByteArray *token;
+       gchar *base64_token;
+
+       /* results */
+       GByteArray *response;
+       gchar *base64_response;
+};
+
 enum {
        PROP_0,
        PROP_AUTHENTICATED,
@@ -62,6 +74,21 @@ enum {
 G_DEFINE_ABSTRACT_TYPE (CamelSasl, camel_sasl, CAMEL_TYPE_OBJECT)
 
 static void
+async_context_free (AsyncContext *async_context)
+{
+       if (async_context->token != NULL)
+               g_byte_array_free (async_context->token, TRUE);
+
+       if (async_context->response != NULL)
+               g_byte_array_free (async_context->response, TRUE);
+
+       g_free (async_context->base64_token);
+       g_free (async_context->base64_response);
+
+       g_slice_free (AsyncContext, async_context);
+}
+
+static void
 sasl_set_mechanism (CamelSasl *sasl,
                     const gchar *mechanism)
 {
@@ -192,6 +219,79 @@ sasl_finalize (GObject *object)
 }
 
 static void
+sasl_challenge_thread (GSimpleAsyncResult *simple,
+                       GObject *object,
+                       GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       async_context->response = camel_sasl_challenge_sync (
+               CAMEL_SASL (object), async_context->token,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+sasl_challenge (CamelSasl *sasl,
+                GByteArray *token,
+                gint io_priority,
+                GCancellable *cancellable,
+                GAsyncReadyCallback callback,
+                gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->token = g_byte_array_new ();
+
+       g_byte_array_append (async_context->token, token->data, token->len);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (sasl), callback, user_data, sasl_challenge);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, sasl_challenge_thread, io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static GByteArray *
+sasl_challenge_finish (CamelSasl *sasl,
+                       GAsyncResult *result,
+                       GError **error)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+       GByteArray *response;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (sasl), sasl_challenge), NULL);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
+
+       response = async_context->response;
+       async_context->response = NULL;
+
+       return response;
+}
+
+static void
 camel_sasl_class_init (CamelSaslClass *class)
 {
        GObjectClass *object_class;
@@ -204,6 +304,9 @@ camel_sasl_class_init (CamelSaslClass *class)
        object_class->dispose = sasl_dispose;
        object_class->finalize = sasl_finalize;
 
+       class->challenge = sasl_challenge;
+       class->challenge_finish = sasl_challenge_finish;
+
        g_object_class_install_property (
                object_class,
                PROP_AUTHENTICATED,
@@ -303,7 +406,7 @@ camel_sasl_new (const gchar *service_name,
 
 /**
  * camel_sasl_get_authenticated:
- * @sasl: a #CamelSasl object
+ * @sasl: a #CamelSasl
  *
  * Returns: whether or not @sasl has successfully authenticated the
  * user. This will be %TRUE after it returns the last needed response.
@@ -380,16 +483,18 @@ camel_sasl_get_service_name (CamelSasl *sasl)
 
 /**
  * camel_sasl_challenge_sync:
- * @sasl: a #CamelSasl object
+ * @sasl: a #CamelSasl
  * @token: a token, or %NULL
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * If @token is %NULL, generate the initial SASL message to send to
- * the server. (This will be %NULL if the client doesn't initiate the
- * exchange.) Otherwise, @token is a challenge from the server, and
+ * the server.  (This will be %NULL if the client doesn't initiate the
+ * exchange.)  Otherwise, @token is a challenge from the server, and
  * the return value is the response.
  *
+ * Free the returned #GByteArray with g_byte_array_free().
+ *
  * Returns: the SASL response or %NULL. If an error occurred, @error will
  * also be set.
  **/
@@ -416,16 +521,86 @@ camel_sasl_challenge_sync (CamelSasl *sasl,
 }
 
 /**
+ * camel_sasl_challenge:
+ * @sasl: a #CamelSasl
+ * @token: a token, or %NULL
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * If @token is %NULL, asynchronously generate the initial SASL message
+ * to send to the server.  (This will be %NULL if the client doesn't
+ * initiate the exchange.)  Otherwise, @token is a challenge from the
+ * server, and the asynchronous result is the response.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_sasl_challenge_finish() to get the result of the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_sasl_challenge (CamelSasl *sasl,
+                      GByteArray *token,
+                      gint io_priority,
+                      GCancellable *cancellable,
+                      GAsyncReadyCallback callback,
+                      gpointer user_data)
+{
+       CamelSaslClass *class;
+
+       g_return_if_fail (CAMEL_IS_SASL (sasl));
+
+       class = CAMEL_SASL_GET_CLASS (sasl);
+       g_return_if_fail (class->challenge != NULL);
+
+       class->challenge (
+               sasl, token, io_priority, cancellable, callback, user_data);
+}
+
+/**
+ * camel_sasl_challenge_finish:
+ * @sasl: a #CamelSasl
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_sasl_challenge().  Free the
+ * returned #GByteArray with g_byte_array_free().
+ *
+ * Returns: the SASL response or %NULL.  If an error occurred, @error will
+ * also be set.
+ *
+ * Since: 2.34
+ **/
+GByteArray *
+camel_sasl_challenge_finish (CamelSasl *sasl,
+                             GAsyncResult *result,
+                             GError **error)
+{
+       CamelSaslClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+       class = CAMEL_SASL_GET_CLASS (sasl);
+       g_return_val_if_fail (class->challenge_finish != NULL, NULL);
+
+       return class->challenge_finish (sasl, result, error);
+}
+
+/**
  * camel_sasl_challenge_base64_sync:
- * @sasl: a #CamelSasl object
+ * @sasl: a #CamelSasl
  * @token: a base64-encoded token
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
- * As with #camel_sasl_challenge, but the challenge @token and the
+ * As with camel_sasl_challenge_sync(), but the challenge @token and the
  * response are both base64-encoded.
  *
- * Returns: the base64 encoded challenge string
+ * Returns: the base64-encoded response
+ *
+ * Since: 2.34
  **/
 gchar *
 camel_sasl_challenge_base64_sync (CamelSasl *sasl,
@@ -433,12 +608,13 @@ camel_sasl_challenge_base64_sync (CamelSasl *sasl,
                                   GCancellable *cancellable,
                                   GError **error)
 {
-       GByteArray *token_binary, *ret_binary;
-       gchar *ret;
+       GByteArray *token_binary;
+       GByteArray *response_binary;
+       gchar *response;
 
        g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
 
-       if (token && *token) {
+       if (token != NULL && *token != '\0') {
                guchar *data;
                gsize length = 0;
 
@@ -449,20 +625,131 @@ camel_sasl_challenge_base64_sync (CamelSasl *sasl,
        } else
                token_binary = NULL;
 
-       ret_binary = camel_sasl_challenge_sync (
+       response_binary = camel_sasl_challenge_sync (
                sasl, token_binary, cancellable, error);
        if (token_binary)
                g_byte_array_free (token_binary, TRUE);
-       if (!ret_binary)
+       if (response_binary == NULL)
                return NULL;
 
-       if (ret_binary->len > 0)
-               ret = g_base64_encode (ret_binary->data, ret_binary->len);
+       if (response_binary->len > 0)
+               response = g_base64_encode (
+                       response_binary->data, response_binary->len);
        else
-               ret = g_strdup ("");
-       g_byte_array_free (ret_binary, TRUE);
+               response = g_strdup ("");
+
+       g_byte_array_free (response_binary, TRUE);
+
+       return response;
+}
+
+/* Helper for camel_sasl_challenge_base64() */
+static void
+sasl_challenge_base64_thread (GSimpleAsyncResult *simple,
+                              GObject *object,
+                              GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       async_context->base64_response = camel_sasl_challenge_base64_sync (
+               CAMEL_SASL (object), async_context->base64_token,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+/**
+ * camel_sasl_challenge_base64:
+ * @sasl: a #CamelSasl
+ * @token: a base64-encoded token
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * As with camel_sasl_challenge(), but the challenge @token and the
+ * response are both base64-encoded.
+ *
+ * When the operation is finished, @callback will be called.  You can
+ * then call camel_store_challenge_base64_finish() to get the result of
+ * the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_sasl_challenge_base64 (CamelSasl *sasl,
+                             const gchar *token,
+                             gint io_priority,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       g_return_if_fail (CAMEL_IS_SASL (sasl));
 
-       return ret;
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->base64_token = g_strdup (token);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (sasl), callback, user_data,
+               camel_sasl_challenge_base64);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, sasl_challenge_base64_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+/**
+ * camel_sasl_challenge_base64_finish:
+ * @sasl: a #CamelSasl
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_sasl_challenge_base64().
+ *
+ * Returns: the base64-encoded response
+ *
+ * Since: 2.34
+ **/
+gchar *
+camel_sasl_challenge_base64_finish (CamelSasl *sasl,
+                                    GAsyncResult *result,
+                                    GError **error)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+       gchar *response;
+
+       g_return_val_if_fail (CAMEL_IS_SASL (sasl), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (sasl), camel_sasl_challenge_base64), NULL);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
+
+       response = async_context->base64_response;
+       async_context->base64_response = NULL;
+
+       return response;
 }
 
 /**
index 57dc1c8..3bb3a84 100644 (file)
@@ -63,10 +63,22 @@ struct _CamelSasl {
 struct _CamelSaslClass {
        CamelObjectClass parent_class;
 
+       /* Synchronous I/O Methods */
        GByteArray *    (*challenge_sync)       (CamelSasl *sasl,
                                                 GByteArray *token,
                                                 GCancellable *cancellable,
                                                 GError **error);
+
+       /* Asynchronous I/O Methods (all have defaults) */
+       void            (*challenge)            (CamelSasl *sasl,
+                                                GByteArray *token,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       GByteArray *    (*challenge_finish)     (CamelSasl *sasl,
+                                                GAsyncResult *result,
+                                                GError **error);
 };
 
 GType          camel_sasl_get_type             (void);
@@ -79,15 +91,35 @@ void                camel_sasl_set_authenticated    (CamelSasl *sasl,
 const gchar *  camel_sasl_get_mechanism        (CamelSasl *sasl);
 CamelService * camel_sasl_get_service          (CamelSasl *sasl);
 const gchar *  camel_sasl_get_service_name     (CamelSasl *sasl);
+
 GByteArray *   camel_sasl_challenge_sync       (CamelSasl *sasl,
                                                 GByteArray *token,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_sasl_challenge            (CamelSasl *sasl,
+                                                GByteArray *token,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+GByteArray *   camel_sasl_challenge_finish     (CamelSasl *sasl,
+                                                GAsyncResult *result,
+                                                GError **error);
 gchar *                camel_sasl_challenge_base64_sync
                                                (CamelSasl *sasl,
                                                 const gchar *token,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_sasl_challenge_base64     (CamelSasl *sasl,
+                                                const gchar *token,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gchar *                camel_sasl_challenge_base64_finish
+                                               (CamelSasl *sasl,
+                                                GAsyncResult *result,
+                                                GError **error);
 
 GList *                camel_sasl_authtype_list        (gboolean include_plain);
 CamelServiceAuthType *
index 58e81d2..309eef1 100644 (file)
@@ -759,7 +759,7 @@ get_hash_from_oid (SECOidTag oidTag)
        return CAMEL_CIPHER_HASH_DEFAULT;
 }
 
-static gint
+static gboolean
 smime_context_sign_sync (CamelCipherContext *context,
                          const gchar *userid,
                          CamelCipherHash hash,
@@ -769,7 +769,6 @@ smime_context_sign_sync (CamelCipherContext *context,
                          GError **error)
 {
        CamelCipherContextClass *class;
-       gint res = -1;
        NSSCMSMessage *cmsg;
        CamelStream *ostream, *istream;
        GByteArray *buffer;
@@ -777,6 +776,7 @@ smime_context_sign_sync (CamelCipherContext *context,
        NSSCMSEncoderContext *enc;
        CamelDataWrapper *dw;
        CamelContentType *ct;
+       gboolean success = FALSE;
 
        class = CAMEL_CIPHER_CONTEXT_GET_CLASS (context);
 
@@ -846,7 +846,7 @@ smime_context_sign_sync (CamelCipherContext *context,
                goto fail;
        }
 
-       res = 0;
+       success = TRUE;
 
        dw = camel_data_wrapper_new ();
        camel_stream_reset (ostream, NULL);
@@ -872,7 +872,7 @@ smime_context_sign_sync (CamelCipherContext *context,
 
                mps = camel_multipart_signed_new ();
                ct = camel_content_type_new ("multipart", "signed");
-               camel_content_type_set_param (ct, "micalg", camel_cipher_hash_to_id (context, get_hash_from_oid (sechash)));
+               camel_content_type_set_param (ct, "micalg", camel_cipher_context_hash_to_id (context, get_hash_from_oid (sechash)));
                camel_content_type_set_param (ct, "protocol", class->sign_protocol);
                camel_data_wrapper_set_mime_type_field ((CamelDataWrapper *)mps, ct);
                camel_content_type_unref (ct);
@@ -904,7 +904,7 @@ fail:
        g_object_unref (ostream);
        g_object_unref (istream);
 
-       return res;
+       return success;
 }
 
 static CamelCipherValidity *
@@ -998,7 +998,7 @@ fail:
        return valid;
 }
 
-static gint
+static gboolean
 smime_context_encrypt_sync (CamelCipherContext *context,
                             const gchar *userid,
                             GPtrArray *recipients,
@@ -1029,7 +1029,7 @@ smime_context_encrypt_sync (CamelCipherContext *context,
        poolp = PORT_NewArena (1024);
        if (poolp == NULL) {
                set_nss_error (error, g_strerror (ENOMEM));
-               return -1;
+               return FALSE;
        }
 
        /* Lookup all recipients certs, for later working */
@@ -1164,7 +1164,7 @@ smime_context_encrypt_sync (CamelCipherContext *context,
        camel_mime_part_set_description (opart, "S/MIME Encrypted Message");
        camel_mime_part_set_encoding (opart, CAMEL_TRANSFER_ENCODING_BASE64);
 
-       return 0;
+       return TRUE;
 
 fail:
        if (ostream)
@@ -1181,7 +1181,7 @@ fail:
 
        PORT_FreeArena (poolp, PR_FALSE);
 
-       return -1;
+       return FALSE;
 }
 
 static CamelCipherValidity *
@@ -1207,9 +1207,12 @@ smime_context_decrypt_sync (CamelCipherContext *context,
        /* FIXME: stream this to the decoder incrementally */
        buffer = g_byte_array_new ();
        istream = camel_stream_mem_new_with_byte_array (buffer);
-       camel_data_wrapper_decode_to_stream_sync (
+       if (!camel_data_wrapper_decode_to_stream_sync (
                camel_medium_get_content (CAMEL_MEDIUM (ipart)),
-               istream, NULL, NULL);
+               istream, cancellable, error)) {
+               g_object_unref (istream);
+               goto fail;
+       }
        camel_stream_reset (istream, NULL);
 
        dec = NSS_CMSDecoder_Start (NULL,
@@ -1352,6 +1355,7 @@ camel_smime_context_describe_part (CamelSMIMEContext *context, CamelMimePart *pa
                /* FIXME: stream this to the decoder incrementally */
                buffer = g_byte_array_new ();
                istream = camel_stream_mem_new_with_byte_array (buffer);
+               /* FIXME Pass a GCancellable and GError here. */
                camel_data_wrapper_decode_to_stream_sync (
                        camel_medium_get_content ((CamelMedium *)part),
                        istream, NULL, NULL);
index fa4997f..f109e57 100644 (file)
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), CAMEL_TYPE_STORE, CamelStorePrivate))
 
+typedef struct _AsyncContext AsyncContext;
+
 struct _CamelStorePrivate {
        GStaticRecMutex folder_lock;    /* for locking folder operations */
 };
 
+struct _AsyncContext {
+       /* arguments */
+       gchar *folder_name_1;
+       gchar *folder_name_2;
+       gboolean expunge;
+       guint32 flags;
+
+       /* results */
+       CamelFolder *folder;
+       CamelFolderInfo *folder_info;
+};
+
 enum {
        FOLDER_CREATED,
        FOLDER_DELETED,
@@ -66,6 +80,20 @@ static guint signals[LAST_SIGNAL];
 
 G_DEFINE_ABSTRACT_TYPE (CamelStore, camel_store, CAMEL_TYPE_SERVICE)
 
+static void
+async_context_free (AsyncContext *async_context)
+{
+       g_free (async_context->folder_name_1);
+       g_free (async_context->folder_name_2);
+
+       if (async_context->folder != NULL)
+               g_object_unref (async_context->folder);
+
+       camel_folder_info_free (async_context->folder_info);
+
+       g_slice_free (AsyncContext, async_context);
+}
+
 /**
  * ignore_no_such_table_exception:
  * Clears the exception 'ex' when it's the 'no such table' exception.
@@ -302,1211 +330,2711 @@ store_noop_sync (CamelStore *store,
 }
 
 static void
-camel_store_class_init (CamelStoreClass *class)
+store_get_folder_thread (GSimpleAsyncResult *simple,
+                         GObject *object,
+                         GCancellable *cancellable)
 {
-       GObjectClass *object_class;
-       CamelServiceClass *service_class;
+       AsyncContext *async_context;
+       GError *error = NULL;
 
-       g_type_class_add_private (class, sizeof (CamelStorePrivate));
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
-       object_class = G_OBJECT_CLASS (class);
-       object_class->finalize = store_finalize;
-       object_class->constructed = store_constructed;
+       async_context->folder = camel_store_get_folder_sync (
+               CAMEL_STORE (object), async_context->folder_name_1,
+               async_context->flags, cancellable, &error);
 
-       service_class = CAMEL_SERVICE_CLASS (class);
-       service_class->construct = store_construct;
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
 
-       class->hash_folder_name = g_str_hash;
-       class->compare_folder_name = g_str_equal;
-       class->can_refresh_folder = store_can_refresh_folder;
-       class->get_inbox_folder_sync = store_get_inbox_folder_sync;
-       class->get_junk_folder_sync = store_get_junk_folder_sync;
-       class->get_trash_folder_sync = store_get_trash_folder_sync;
-       class->synchronize_sync = store_synchronize_sync;
-       class->noop_sync = store_noop_sync;
+static void
+store_get_folder (CamelStore *store,
+                  const gchar *folder_name,
+                  guint32 flags,
+                  gint io_priority,
+                  GCancellable *cancellable,
+                  GAsyncReadyCallback callback,
+                  gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       signals[FOLDER_CREATED] = g_signal_new (
-               "folder-created",
-               G_OBJECT_CLASS_TYPE (class),
-               G_SIGNAL_RUN_FIRST,
-               G_STRUCT_OFFSET (CamelStoreClass, folder_created),
-               NULL, NULL,
-               g_cclosure_marshal_VOID__POINTER,
-               G_TYPE_NONE, 1,
-               G_TYPE_POINTER);
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->folder_name_1 = g_strdup (folder_name);
+       async_context->flags = flags;
 
-       signals[FOLDER_DELETED] = g_signal_new (
-               "folder-deleted",
-               G_OBJECT_CLASS_TYPE (class),
-               G_SIGNAL_RUN_FIRST,
-               G_STRUCT_OFFSET (CamelStoreClass, folder_deleted),
-               NULL, NULL,
-               g_cclosure_marshal_VOID__POINTER,
-               G_TYPE_NONE, 1,
-               G_TYPE_POINTER);
+       simple = g_simple_async_result_new (
+               G_OBJECT (store), callback, user_data, store_get_folder);
 
-       signals[FOLDER_OPENED] = g_signal_new (
-               "folder-opened",
-               G_OBJECT_CLASS_TYPE (class),
-               G_SIGNAL_RUN_FIRST,
-               G_STRUCT_OFFSET (CamelStoreClass, folder_opened),
-               NULL, NULL,
-               g_cclosure_marshal_VOID__OBJECT,
-               G_TYPE_NONE, 1,
-               CAMEL_TYPE_FOLDER);
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
 
-       signals[FOLDER_RENAMED] = g_signal_new (
-               "folder-renamed",
-               G_OBJECT_CLASS_TYPE (class),
-               G_SIGNAL_RUN_FIRST,
-               G_STRUCT_OFFSET (CamelStoreClass, folder_renamed),
-               NULL, NULL,
-               camel_marshal_VOID__STRING_POINTER,
-               G_TYPE_NONE, 2,
-               G_TYPE_STRING,
-               G_TYPE_POINTER);
+       g_simple_async_result_run_in_thread (
+               simple, store_get_folder_thread, io_priority, cancellable);
 
-       signals[FOLDER_SUBSCRIBED] = g_signal_new (
-               "folder-subscribed",
-               G_OBJECT_CLASS_TYPE (class),
-               G_SIGNAL_RUN_FIRST,
-               G_STRUCT_OFFSET (CamelStoreClass, folder_subscribed),
-               NULL, NULL,
-               g_cclosure_marshal_VOID__POINTER,
-               G_TYPE_NONE, 1,
-               G_TYPE_POINTER);
+       g_object_unref (simple);
+}
 
-       signals[FOLDER_UNSUBSCRIBED] = g_signal_new (
-               "folder-unsubscribed",
-               G_OBJECT_CLASS_TYPE (class),
-               G_SIGNAL_RUN_FIRST,
-               G_STRUCT_OFFSET (CamelStoreClass, folder_unsubscribed),
-               NULL, NULL,
-               g_cclosure_marshal_VOID__POINTER,
-               G_TYPE_NONE, 1,
-               G_TYPE_POINTER);
+static CamelFolder *
+store_get_folder_finish (CamelStore *store,
+                         GAsyncResult *result,
+                         GError **error)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (store), store_get_folder), NULL);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
+
+       return g_object_ref (async_context->folder);
 }
 
 static void
-camel_store_init (CamelStore *store)
+store_get_folder_info_thread (GSimpleAsyncResult *simple,
+                              GObject *object,
+                              GCancellable *cancellable)
 {
-       store->priv = CAMEL_STORE_GET_PRIVATE (store);
+       AsyncContext *async_context;
+       GError *error = NULL;
 
-       /* set vtrash and vjunk on by default */
-       store->flags = CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK;
-       store->mode = CAMEL_STORE_READ | CAMEL_STORE_WRITE;
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
-       g_static_rec_mutex_init (&store->priv->folder_lock);
+       async_context->folder_info = camel_store_get_folder_info_sync (
+               CAMEL_STORE (object), async_context->folder_name_1,
+               async_context->flags, cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
 }
 
-GQuark
-camel_store_error_quark (void)
+static void
+store_get_folder_info (CamelStore *store,
+                       const gchar *top,
+                       guint32 flags,
+                       gint io_priority,
+                       GCancellable *cancellable,
+                       GAsyncReadyCallback callback,
+                       gpointer user_data)
 {
-       static GQuark quark = 0;
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       if (G_UNLIKELY (quark == 0)) {
-               const gchar *string = "camel-store-error-quark";
-               quark = g_quark_from_static_string (string);
-       }
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->folder_name_1 = g_strdup (top);
+       async_context->flags = flags;
 
-       return quark;
+       simple = g_simple_async_result_new (
+               G_OBJECT (store), callback,
+               user_data, store_get_folder_info);
+
+       g_simple_async_result_run_in_thread (
+               simple, store_get_folder_info_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
 }
 
-/**
- * camel_store_get_folder_sync:
- * @store: a #CamelStore object
- * @folder_name: name of the folder to get
- * @flags: folder flags (create, save body index, etc)
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Get a specific folder object from the store by name.
- *
- * Returns: the folder corresponding to the path @folder_name or %NULL.
- **/
-CamelFolder *
-camel_store_get_folder_sync (CamelStore *store,
-                             const gchar *folder_name,
-                             guint32 flags,
-                             GCancellable *cancellable,
-                             GError **error)
+static CamelFolderInfo *
+store_get_folder_info_finish (CamelStore *store,
+                              GAsyncResult *result,
+                              GError **error)
 {
-       CamelStoreClass *class;
-       CamelFolder *folder = NULL;
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+       CamelFolderInfo *folder_info;
 
-       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
-       g_return_val_if_fail (folder_name != NULL, NULL);
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (store), store_get_folder_info), NULL);
 
-       class = CAMEL_STORE_GET_CLASS (store);
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
-       /* O_EXCL doesn't make sense if we aren't requesting to also create the folder if it doesn't exist */
-       if (!(flags & CAMEL_STORE_FOLDER_CREATE))
-               flags &= ~CAMEL_STORE_FOLDER_EXCL;
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
 
-       if (store->folders) {
-               /* Try cache first. */
-               folder = camel_object_bag_reserve (store->folders, folder_name);
-               if (folder && (flags & CAMEL_STORE_FOLDER_EXCL)) {
-                       g_set_error (
-                               error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
-                               _("Cannot create folder '%s': folder exists"),
-                               folder_name);
-                        camel_object_bag_abort (store->folders, folder_name);
-                       g_object_unref (folder);
-                       return NULL;
-               }
-       }
+       folder_info = async_context->folder_info;
+       async_context->folder_info = NULL;
 
-       if (!folder) {
+       return folder_info;
+}
 
-               if (flags & CAMEL_STORE_IS_MIGRATING) {
-                       if ((store->flags & CAMEL_STORE_VTRASH) && strcmp (folder_name, CAMEL_VTRASH_NAME) == 0) {
-                               if (store->folders)
-                                       camel_object_bag_abort (store->folders, folder_name);
-                               return NULL;
-                       }
+static void
+store_get_inbox_folder_thread (GSimpleAsyncResult *simple,
+                               GObject *object,
+                               GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
 
-                       if ((store->flags & CAMEL_STORE_VJUNK) && strcmp (folder_name, CAMEL_VJUNK_NAME) == 0) {
-                               if (store->folders)
-                                               camel_object_bag_abort (store->folders, folder_name);
-                               return NULL;
-                       }
-               }
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
-               if ((store->flags & CAMEL_STORE_VTRASH) && strcmp(folder_name, CAMEL_VTRASH_NAME) == 0) {
-                       folder = class->get_trash_folder_sync (store, cancellable, error);
-                       CAMEL_CHECK_GERROR (store, get_trash_folder_sync, folder != NULL, error);
-               } else if ((store->flags & CAMEL_STORE_VJUNK) && strcmp(folder_name, CAMEL_VJUNK_NAME) == 0) {
-                       folder = class->get_junk_folder_sync (store, cancellable, error);
-                       CAMEL_CHECK_GERROR (store, get_junk_folder_sync, folder != NULL, error);
-               } else {
-                       folder = class->get_folder_sync (
-                               store, folder_name, flags, cancellable, error);
-                       CAMEL_CHECK_GERROR (store, get_folder_sync, folder != NULL, error);
+       async_context->folder = camel_store_get_inbox_folder_sync (
+               CAMEL_STORE (object), cancellable, &error);
 
-                       if (folder) {
-                               CamelVeeFolder *vfolder;
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
 
-                               if ((store->flags & CAMEL_STORE_VTRASH)
-                                   && (vfolder = camel_object_bag_get (store->folders, CAMEL_VTRASH_NAME))) {
-                                       camel_vee_folder_add_folder (vfolder, folder);
-                                       g_object_unref (vfolder);
-                               }
+static void
+store_get_inbox_folder (CamelStore *store,
+                        gint io_priority,
+                        GCancellable *cancellable,
+                        GAsyncReadyCallback callback,
+                        gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-                               if ((store->flags & CAMEL_STORE_VJUNK)
-                                   && (vfolder = camel_object_bag_get (store->folders, CAMEL_VJUNK_NAME))) {
-                                       camel_vee_folder_add_folder (vfolder, folder);
-                                       g_object_unref (vfolder);
-                               }
-                       }
-               }
+       async_context = g_slice_new0 (AsyncContext);
 
-               if (store->folders) {
-                       if (folder)
-                               camel_object_bag_add (store->folders, folder_name, folder);
-                       else
-                               camel_object_bag_abort (store->folders, folder_name);
-               }
+       simple = g_simple_async_result_new (
+               G_OBJECT (store), callback,
+               user_data, store_get_inbox_folder);
 
-               if (folder)
-                       g_signal_emit (store, signals[FOLDER_OPENED], 0, folder);
-       }
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
 
-       return folder;
+       g_simple_async_result_run_in_thread (
+               simple, store_get_inbox_folder_thread,
+               io_priority, cancellable);
+
+       g_object_unref (simple);
 }
 
-/**
- * camel_store_create_folder_sync:
- * @store: a #CamelStore object
- * @parent_name: name of the new folder's parent, or %NULL
- * @folder_name: name of the folder to create
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Creates a new folder as a child of an existing folder.
- * @parent_name can be %NULL to create a new top-level folder.
- *
- * Returns: info about the created folder, which the caller must
- * free with #camel_store_free_folder_info, or %NULL.
- **/
-CamelFolderInfo *
-camel_store_create_folder_sync (CamelStore *store,
-                                const gchar *parent_name,
-                                const gchar *folder_name,
-                                GCancellable *cancellable,
-                                GError **error)
+static CamelFolder *
+store_get_inbox_folder_finish (CamelStore *store,
+                               GAsyncResult *result,
+                               GError **error)
 {
-       CamelStoreClass *class;
-       CamelFolderInfo *fi;
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
-       g_return_val_if_fail (folder_name != NULL, NULL);
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (store), store_get_inbox_folder), NULL);
 
-       class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->create_folder_sync != NULL, NULL);
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
-       if ((parent_name == NULL || parent_name[0] == 0)
-           && (((store->flags & CAMEL_STORE_VTRASH) && strcmp (folder_name, CAMEL_VTRASH_NAME) == 0)
-               || ((store->flags & CAMEL_STORE_VJUNK) && strcmp (folder_name, CAMEL_VJUNK_NAME) == 0))) {
-               g_set_error (
-                       error, CAMEL_STORE_ERROR,
-                       CAMEL_STORE_ERROR_INVALID,
-                       _("Cannot create folder: %s: folder exists"),
-                       folder_name);
+       if (g_simple_async_result_propagate_error (simple, error))
                return NULL;
-       }
 
-       camel_store_lock (store, CAMEL_STORE_FOLDER_LOCK);
+       return g_object_ref (async_context->folder);
+}
 
-       fi = class->create_folder_sync (
-               store, parent_name, folder_name, cancellable, error);
-       CAMEL_CHECK_GERROR (store, create_folder_sync, fi != NULL, error);
+static void
+store_get_junk_folder_thread (GSimpleAsyncResult *simple,
+                              GObject *object,
+                              GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
 
-       camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
-       return fi;
+       async_context->folder = camel_store_get_junk_folder_sync (
+               CAMEL_STORE (object), cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
 }
 
-/* deletes folder/removes it from the folder cache, if it's there */
 static void
-cs_delete_cached_folder (CamelStore *store,
-                         const gchar *folder_name)
+store_get_junk_folder (CamelStore *store,
+                       gint io_priority,
+                       GCancellable *cancellable,
+                       GAsyncReadyCallback callback,
+                       gpointer user_data)
 {
-       CamelFolder *folder;
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       if (store->folders
-           && (folder = camel_object_bag_get (store->folders, folder_name))) {
-               CamelVeeFolder *vfolder;
+       async_context = g_slice_new0 (AsyncContext);
 
-               if ((store->flags & CAMEL_STORE_VTRASH)
-                   && (vfolder = camel_object_bag_get(store->folders, CAMEL_VTRASH_NAME))) {
-                       camel_vee_folder_remove_folder (vfolder, folder);
-                       g_object_unref (vfolder);
-               }
+       simple = g_simple_async_result_new (
+               G_OBJECT (store), callback,
+               user_data, store_get_junk_folder);
 
-               if ((store->flags & CAMEL_STORE_VJUNK)
-                   && (vfolder = camel_object_bag_get(store->folders, CAMEL_VJUNK_NAME))) {
-                       camel_vee_folder_remove_folder(vfolder, folder);
-                       g_object_unref (vfolder);
-               }
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
 
-               camel_folder_delete (folder);
+       g_simple_async_result_run_in_thread (
+               simple, store_get_junk_folder_thread,
+               io_priority, cancellable);
 
-               camel_object_bag_remove (store->folders, folder);
-               g_object_unref (folder);
-       }
+       g_object_unref (simple);
 }
 
-/**
- * camel_store_delete_folder_sync:
- * @store: a #CamelStore object
- * @folder_name: name of the folder to delete
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Deletes the named folder. The folder must be empty.
- *
- * Returns: %TRUE on success, %FALSE on failure
- **/
-gboolean
-camel_store_delete_folder_sync (CamelStore *store,
-                                const gchar *folder_name,
-                                GCancellable *cancellable,
-                                GError **error)
+static CamelFolder *
+store_get_junk_folder_finish (CamelStore *store,
+                              GAsyncResult *result,
+                              GError **error)
 {
-       CamelStoreClass *class;
-       gboolean success;
-       GError *local_error = NULL;
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
-       g_return_val_if_fail (folder_name != NULL, FALSE);
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (store), store_get_folder), NULL);
 
-       class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->delete_folder_sync != NULL, FALSE);
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
-       /* TODO: should probably be a parameter/bit on the storeinfo */
-       if (((store->flags & CAMEL_STORE_VTRASH) && strcmp (folder_name, CAMEL_VTRASH_NAME) == 0)
-           || ((store->flags & CAMEL_STORE_VJUNK) && strcmp (folder_name, CAMEL_VJUNK_NAME) == 0)) {
-               g_set_error (
-                       error, CAMEL_STORE_ERROR,
-                       CAMEL_STORE_ERROR_NO_FOLDER,
-                       _("Cannot delete folder: %s: Invalid operation"),
-                       folder_name);
-               return FALSE;
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
+
+       return g_object_ref (async_context->folder);
+}
+
+static void
+store_get_trash_folder_thread (GSimpleAsyncResult *simple,
+                               GObject *object,
+                               GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       async_context->folder = camel_store_get_trash_folder_sync (
+               CAMEL_STORE (object), cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
        }
+}
 
-       camel_store_lock (store, CAMEL_STORE_FOLDER_LOCK);
+static void
+store_get_trash_folder (CamelStore *store,
+                        gint io_priority,
+                        GCancellable *cancellable,
+                        GAsyncReadyCallback callback,
+                        gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       success = class->delete_folder_sync (
-               store, folder_name, cancellable, &local_error);
-       CAMEL_CHECK_GERROR (store, delete_folder_sync, success, &local_error);
+       async_context = g_slice_new0 (AsyncContext);
 
-       /* ignore 'no such table' errors */
-       if (local_error != NULL &&
-           g_ascii_strncasecmp (local_error->message, "no such table", 13) == 0)
-               g_clear_error (&local_error);
+       simple = g_simple_async_result_new (
+               G_OBJECT (store), callback,
+               user_data, store_get_trash_folder);
 
-       if (local_error == NULL)
-               cs_delete_cached_folder(store, folder_name);
-       else
-               g_propagate_error (error, local_error);
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
 
-       camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+       g_simple_async_result_run_in_thread (
+               simple, store_get_trash_folder_thread,
+               io_priority, cancellable);
 
-       return success;
+       g_object_unref (simple);
 }
 
-/**
- * camel_store_rename_folder_sync:
- * @store: a #CamelStore object
- * @old_namein: the current name of the folder
- * @new_name: the new name of the folder
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Rename a named folder to a new name.
- *
- * Returns: %TRUE on success, %FALSE on failure
- **/
-gboolean
-camel_store_rename_folder_sync (CamelStore *store,
-                                const gchar *old_namein,
-                                const gchar *new_name,
-                                GCancellable *cancellable,
-                                GError **error)
+static CamelFolder *
+store_get_trash_folder_finish (CamelStore *store,
+                               GAsyncResult *result,
+                               GError **error)
 {
-       CamelStoreClass *class;
-       CamelFolder *folder;
-       gint i, oldlen, namelen;
-       GPtrArray *folders = NULL;
-       gchar *old_name;
-       gboolean success;
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
-       g_return_val_if_fail (old_namein != NULL, FALSE);
-       g_return_val_if_fail (new_name != NULL, FALSE);
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (store), store_get_trash_folder), NULL);
 
-       class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->rename_folder_sync != NULL, FALSE);
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
-       if (strcmp (old_namein, new_name) == 0)
-               return TRUE;
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
 
-       if (((store->flags & CAMEL_STORE_VTRASH) && strcmp (old_namein, CAMEL_VTRASH_NAME) == 0)
-           || ((store->flags & CAMEL_STORE_VJUNK) && strcmp (old_namein, CAMEL_VJUNK_NAME) == 0)) {
-               g_set_error (
-                       error, CAMEL_STORE_ERROR,
-                       CAMEL_STORE_ERROR_NO_FOLDER,
-                       _("Cannot rename folder: %s: Invalid operation"),
-                       old_namein);
-               return FALSE;
+       return g_object_ref (async_context->folder);
+}
+
+static void
+store_create_folder_thread (GSimpleAsyncResult *simple,
+                            GObject *object,
+                            GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       async_context->folder_info = camel_store_create_folder_sync (
+               CAMEL_STORE (object), async_context->folder_name_1,
+               async_context->folder_name_2, cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
        }
+}
 
-       /* need to save this, since old_namein might be folder->full_name, which could go away */
-       old_name = g_strdup (old_namein);
-       oldlen = strlen (old_name);
+static void
+store_create_folder (CamelStore *store,
+                     const gchar *parent_name,
+                     const gchar *folder_name,
+                     gint io_priority,
+                     GCancellable *cancellable,
+                     GAsyncReadyCallback callback,
+                     gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       camel_store_lock (store, CAMEL_STORE_FOLDER_LOCK);
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->folder_name_1 = g_strdup (parent_name);
+       async_context->folder_name_2 = g_strdup (folder_name);
 
-       /* If the folder is open (or any subfolders of the open folder)
-          We need to rename them atomically with renaming the actual folder path */
-       if (store->folders) {
-               folders = camel_object_bag_list (store->folders);
-               for (i=0;i<folders->len;i++) {
-                       const gchar *full_name;
+       simple = g_simple_async_result_new (
+               G_OBJECT (store), callback, user_data, store_create_folder);
 
-                       folder = folders->pdata[i];
-                       full_name = camel_folder_get_full_name (folder);
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
 
-                       namelen = strlen (full_name);
-                       if ((namelen == oldlen &&
-                            strcmp (full_name, old_name) == 0)
-                           || ((namelen > oldlen)
-                               && strncmp (full_name, old_name, oldlen) == 0
-                               && full_name[oldlen] == '/')) {
-                               camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
-                       } else {
-                               g_ptr_array_remove_index_fast (folders, i);
-                               i--;
-                               g_object_unref (folder);
-                       }
-               }
-       }
+       g_simple_async_result_run_in_thread (
+               simple, store_create_folder_thread, io_priority, cancellable);
 
-       /* Now try the real rename (will emit renamed signal) */
-       success = class->rename_folder_sync (
-               store, old_name, new_name, cancellable, error);
-       CAMEL_CHECK_GERROR (store, rename_folder_sync, success, error);
+       g_object_unref (simple);
+}
 
-       /* If it worked, update all open folders/unlock them */
-       if (folders) {
-               if (success) {
-                       guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE;
-                       CamelFolderInfo *folder_info;
+static CamelFolderInfo *
+store_create_folder_finish (CamelStore *store,
+                            GAsyncResult *result,
+                            GError **error)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+       CamelFolderInfo *folder_info;
 
-                       for (i=0;i<folders->len;i++) {
-                               const gchar *full_name;
-                               gchar *new;
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (store), store_create_folder_finish), NULL);
 
-                               folder = folders->pdata[i];
-                               full_name = camel_folder_get_full_name (folder);
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
-                               new = g_strdup_printf("%s%s", new_name, full_name + strlen(old_name));
-                               camel_object_bag_rekey (store->folders, folder, new);
-                               camel_folder_rename (folder, new);
-                               g_free (new);
+       if (g_simple_async_result_propagate_error (simple, error))
+               return NULL;
 
-                               camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
-                               g_object_unref (folder);
-                       }
+       folder_info = async_context->folder_info;
+       async_context->folder_info = NULL;
 
-                       /* Emit renamed signal */
-                       if (store->flags & CAMEL_STORE_SUBSCRIPTIONS)
-                               flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
+       return folder_info;
+}
 
-                       folder_info = class->get_folder_info_sync (
-                               store, new_name, flags, cancellable, error);
-                       CAMEL_CHECK_GERROR (store, get_folder_info, folder_info != NULL, error);
+static void
+store_delete_folder_thread (GSimpleAsyncResult *simple,
+                            GObject *object,
+                            GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
 
-                       if (folder_info != NULL) {
-                               camel_store_folder_renamed (store, old_name, folder_info);
-                               class->free_folder_info (store, folder_info);
-                       }
-               } else {
-                       /* Failed, just unlock our folders for re-use */
-                       for (i=0;i<folders->len;i++) {
-                               folder = folders->pdata[i];
-                               camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
-                               g_object_unref (folder);
-                       }
-               }
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_store_delete_folder_sync (
+               CAMEL_STORE (object), async_context->folder_name_1,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
        }
+}
 
-       camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+static void
+store_delete_folder (CamelStore *store,
+                     const gchar *folder_name,
+                     gint io_priority,
+                     GCancellable *cancellable,
+                     GAsyncReadyCallback callback,
+                     gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       g_ptr_array_free (folders, TRUE);
-       g_free (old_name);
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->folder_name_1 = g_strdup (folder_name);
 
-       return success;
+       simple = g_simple_async_result_new (
+               G_OBJECT (store), callback, user_data, store_delete_folder);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, store_delete_folder_thread, io_priority, cancellable);
+
+       g_object_unref (simple);
 }
 
-/**
- * camel_store_folder_created:
- * @store: a #CamelStore
- * @info: information about the created folder
- *
- * Emits the #CamelStore::folder-created signal.
- *
- * This function is only intended for Camel providers.
- *
- * Since: 2.32
- **/
-void
-camel_store_folder_created (CamelStore *store,
-                            CamelFolderInfo *info)
+static gboolean
+store_delete_folder_finish (CamelStore *store,
+                            GAsyncResult *result,
+                            GError **error)
 {
-       g_return_if_fail (CAMEL_STORE (store));
-       g_return_if_fail (info != NULL);
+       GSimpleAsyncResult *simple;
 
-       g_signal_emit (store, signals[FOLDER_CREATED], 0, info);
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (store), store_delete_folder), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
 }
 
-/**
- * camel_store_folder_deleted:
- * @store: a #CamelStore
- * @info: information about the deleted folder
- *
- * Emits the #CamelStore::folder-deleted signal.
- *
- * This function is only intended for Camel providers.
- *
- * Since: 2.32
- **/
-void
-camel_store_folder_deleted (CamelStore *store,
-                            CamelFolderInfo *info)
+static void
+store_rename_folder_thread (GSimpleAsyncResult *simple,
+                            GObject *object,
+                            GCancellable *cancellable)
 {
-       g_return_if_fail (CAMEL_STORE (store));
-       g_return_if_fail (info != NULL);
+       AsyncContext *async_context;
+       GError *error = NULL;
 
-       g_signal_emit (store, signals[FOLDER_DELETED], 0, info);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_store_rename_folder_sync (
+               CAMEL_STORE (object), async_context->folder_name_1,
+               async_context->folder_name_2, cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
 }
 
-/**
- * camel_store_folder_renamed:
- * @store: a #CamelStore
- * @old_name: the old name of the folder
- * @info: information about the renamed folder
- *
- * Emits the #CamelStore::folder-renamed signal.
- *
- * This function is only intended for Camel providers.
- *
- * Since: 2.32
- **/
-void
-camel_store_folder_renamed (CamelStore *store,
-                            const gchar *old_name,
-                            CamelFolderInfo *info)
+static void
+store_rename_folder (CamelStore *store,
+                     const gchar *old_name,
+                     const gchar *new_name,
+                     gint io_priority,
+                     GCancellable *cancellable,
+                     GAsyncReadyCallback callback,
+                     gpointer user_data)
 {
-       g_return_if_fail (CAMEL_STORE (store));
-       g_return_if_fail (old_name != NULL);
-       g_return_if_fail (info != NULL);
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       g_signal_emit (store, signals[FOLDER_RENAMED], 0, old_name, info);
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->folder_name_1 = g_strdup (old_name);
+       async_context->folder_name_2 = g_strdup (new_name);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (store), callback, user_data, store_rename_folder);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, store_rename_folder_thread, io_priority, cancellable);
+
+       g_object_unref (simple);
 }
 
-/**
- * camel_store_folder_subscribed:
- * @store: a #CamelStore
- * @info: information about the subscribed folder
- *
- * Emits the #CamelStore::folder-subscribed signal.
- *
- * This function is only intended for Camel providers.
- *
- * Since: 2.32
- **/
-void
-camel_store_folder_subscribed (CamelStore *store,
-                               CamelFolderInfo *info)
+static gboolean
+store_rename_folder_finish (CamelStore *store,
+                            GAsyncResult *result,
+                            GError **error)
 {
-       g_return_if_fail (CAMEL_STORE (store));
-       g_return_if_fail (info != NULL);
+       GSimpleAsyncResult *simple;
 
-       g_signal_emit (store, signals[FOLDER_SUBSCRIBED], 0, info);
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (store), store_rename_folder), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
 }
 
-/**
- * camel_store_folder_unsubscribed:
- * @store: a #CamelStore
- * @info: information about the unsubscribed folder
- *
- * Emits the #CamelStore::folder-unsubscribed signal.
- *
- * This function is only intended for Camel providers.
- *
- * Since: 2.32
- **/
-void
-camel_store_folder_unsubscribed (CamelStore *store,
-                                 CamelFolderInfo *info)
+static void
+store_subscribe_folder_thread (GSimpleAsyncResult *simple,
+                               GObject *object,
+                               GCancellable *cancellable)
 {
-       g_return_if_fail (CAMEL_STORE (store));
-       g_return_if_fail (info != NULL);
+       AsyncContext *async_context;
+       GError *error = NULL;
 
-       g_signal_emit (store, signals[FOLDER_UNSUBSCRIBED], 0, info);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_store_subscribe_folder_sync (
+               CAMEL_STORE (object), async_context->folder_name_1,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
 }
 
-/**
- * camel_store_get_inbox_folder_sync:
- * @store: a #CamelStore object
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Returns: the folder in the store into which new mail is delivered,
- * or %NULL if no such folder exists.
- **/
-CamelFolder *
-camel_store_get_inbox_folder_sync (CamelStore *store,
-                                   GCancellable *cancellable,
-                                   GError **error)
+static void
+store_subscribe_folder (CamelStore *store,
+                        const gchar *folder_name,
+                        gint io_priority,
+                        GCancellable *cancellable,
+                        GAsyncReadyCallback callback,
+                        gpointer user_data)
 {
-       CamelStoreClass *class;
-       CamelFolder *folder;
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
-
-       class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->get_inbox_folder_sync != NULL, NULL);
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->folder_name_1 = g_strdup (folder_name);
 
-       camel_store_lock (store, CAMEL_STORE_FOLDER_LOCK);
+       simple = g_simple_async_result_new (
+               G_OBJECT (store), callback,
+               user_data, store_subscribe_folder);
 
-       folder = class->get_inbox_folder_sync (store, cancellable, error);
-       CAMEL_CHECK_GERROR (
-               store, get_inbox_folder_sync, folder != NULL, error);
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
 
-       camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+       g_simple_async_result_run_in_thread (
+               simple, store_subscribe_folder_thread,
+               io_priority, cancellable);
 
-       return folder;
+       g_object_unref (simple);
 }
 
-/**
- * camel_store_get_junk_folder_sync:
- * @store: a #CamelStore object
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Returns: the folder in the store into which junk is delivered, or
- * %NULL if no such folder exists.
- **/
-CamelFolder *
-camel_store_get_junk_folder_sync (CamelStore *store,
-                                  GCancellable *cancellable,
-                                  GError **error)
+static gboolean
+store_subscribe_folder_finish (CamelStore *store,
+                               GAsyncResult *result,
+                               GError **error)
 {
-       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+       GSimpleAsyncResult *simple;
 
-       if ((store->flags & CAMEL_STORE_VJUNK) == 0) {
-               CamelStoreClass *class;
-               CamelFolder *folder;
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (store), store_subscribe_folder), FALSE);
 
-               class = CAMEL_STORE_GET_CLASS (store);
-               g_return_val_if_fail (class->get_junk_folder_sync != NULL, NULL);
+       simple = G_SIMPLE_ASYNC_RESULT (result);
 
-               folder = class->get_junk_folder_sync (store, cancellable, error);
-               CAMEL_CHECK_GERROR (
-                       store, get_junk_folder_sync, folder != NULL, error);
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
 
-               return folder;
-       }
+static void
+store_unsubscribe_folder_thread (GSimpleAsyncResult *simple,
+                                 GObject *object,
+                                 GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
 
-       return camel_store_get_folder_sync (
-               store, CAMEL_VJUNK_NAME, 0, cancellable, error);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_store_unsubscribe_folder_sync (
+               CAMEL_STORE (object), async_context->folder_name_1,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
 }
 
-/**
- * camel_store_get_trash_folder_sync:
- * @store: a #CamelStore object
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Returns: the folder in the store into which trash is delivered, or
- * %NULL if no such folder exists.
- **/
-CamelFolder *
-camel_store_get_trash_folder_sync (CamelStore *store,
-                                   GCancellable *cancellable,
-                                   GError **error)
+static void
+store_unsubscribe_folder (CamelStore *store,
+                          const gchar *folder_name,
+                          gint io_priority,
+                          GCancellable *cancellable,
+                          GAsyncReadyCallback callback,
+                          gpointer user_data)
 {
-       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       if ((store->flags & CAMEL_STORE_VTRASH) == 0) {
-               CamelStoreClass *class;
-               CamelFolder *folder;
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->folder_name_1 = g_strdup (folder_name);
 
-               class = CAMEL_STORE_GET_CLASS (store);
-               g_return_val_if_fail (class->get_trash_folder_sync != NULL, NULL);
+       simple = g_simple_async_result_new (
+               G_OBJECT (store), callback,
+               user_data, store_unsubscribe_folder);
 
-               folder = class->get_trash_folder_sync (
-                       store, cancellable, error);
-               CAMEL_CHECK_GERROR (
-                       store, get_trash_folder_sync, folder != NULL, error);
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
 
-               return folder;
-       }
+       g_simple_async_result_run_in_thread (
+               simple, store_unsubscribe_folder_thread,
+               io_priority, cancellable);
 
-       return camel_store_get_folder_sync (
-               store, CAMEL_VTRASH_NAME, 0, cancellable, error);
+       g_object_unref (simple);
 }
 
-/**
- * camel_store_synchronize_sync:
- * @store: a #CamelStore object
- * @expunge: %TRUE if an expunge should be done after sync or %FALSE otherwise
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * Syncs any changes that have been made to the store object and its
- * folders with the real store.
- *
- * Returns: %TRUE on success, %FALSE on failure
- **/
-gboolean
-camel_store_synchronize_sync (CamelStore *store,
-                              gboolean expunge,
-                              GCancellable *cancellable,
-                              GError **error)
+static gboolean
+store_unsubscribe_folder_finish (CamelStore *store,
+                                 GAsyncResult *result,
+                                 GError **error)
 {
-       CamelStoreClass *class;
-       gboolean success;
-
-       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       GSimpleAsyncResult *simple;
 
-       class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->synchronize_sync != NULL, FALSE);
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (store), store_unsubscribe_folder), FALSE);
 
-       success = class->synchronize_sync (store, expunge, cancellable, error);
-       CAMEL_CHECK_GERROR (store, synchronize_sync, success, error);
+       simple = G_SIMPLE_ASYNC_RESULT (result);
 
-       return success;
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
 }
 
 static void
-add_special_info (CamelStore *store,
-                  CamelFolderInfo *info,
-                  const gchar *name,
-                  const gchar *translated,
-                  gboolean unread_count,
-                  guint32 flags)
+store_synchronize_thread (GSimpleAsyncResult *simple,
+                          GObject *object,
+                          GCancellable *cancellable)
 {
-       CamelFolderInfo *fi, *vinfo, *parent;
-       gchar *uri, *path;
-       CamelURL *url;
+       AsyncContext *async_context;
+       GError *error = NULL;
 
-       g_return_if_fail (info != NULL);
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
 
-       parent = NULL;
-       for (fi = info; fi; fi = fi->next) {
-               if (!strcmp (fi->full_name, name))
-                       break;
-               parent = fi;
-       }
+       camel_store_synchronize_sync (
+               CAMEL_STORE (object), async_context->expunge,
+               cancellable, &error);
 
-       /* create our vTrash/vJunk URL */
-       url = camel_url_new (info->uri, NULL);
-       if (((CamelService *) store)->provider->url_flags & CAMEL_URL_FRAGMENT_IS_PATH) {
-               camel_url_set_fragment (url, name);
-       } else {
-               path = g_strdup_printf ("/%s", name);
-               camel_url_set_path (url, path);
-               g_free (path);
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
        }
+}
 
-       uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
-       camel_url_free (url);
+static void
+store_synchronize (CamelStore *store,
+                   gboolean expunge,
+                   gint io_priority,
+                   GCancellable *cancellable,
+                   GAsyncReadyCallback callback,
+                   gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
 
-       if (fi) {
-               /* We're going to replace the physical Trash/Junk folder with our vTrash/vJunk folder */
-               vinfo = fi;
-               g_free (vinfo->full_name);
-               g_free (vinfo->name);
-               g_free (vinfo->uri);
-       } else {
-               /* There wasn't a Trash/Junk folder so create a new folder entry */
-               vinfo = camel_folder_info_new ();
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->expunge = expunge;
 
-               g_assert (parent != NULL);
+       simple = g_simple_async_result_new (
+               G_OBJECT (store), callback, user_data, store_synchronize);
 
-               vinfo->flags |= CAMEL_FOLDER_NOINFERIORS | CAMEL_FOLDER_SUBSCRIBED;
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
 
-               /* link it into the right spot */
-               vinfo->next = parent->next;
-               parent->next = vinfo;
-       }
+       g_simple_async_result_run_in_thread (
+               simple, store_synchronize_thread, io_priority, cancellable);
 
-       /* Fill in the new fields */
-       vinfo->flags |= flags;
-       vinfo->full_name = g_strdup (name);
-       vinfo->name = g_strdup (translated);
-       vinfo->uri = uri;
-       if (!unread_count)
-               vinfo->unread = -1;
+       g_object_unref (simple);
+}
+
+static gboolean
+store_synchronize_finish (CamelStore *store,
+                          GAsyncResult *result,
+                          GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (store), store_synchronize), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
 }
 
 static void
-dump_fi (CamelFolderInfo *fi, gint depth)
+store_noop_thread (GSimpleAsyncResult *simple,
+                   GObject *object,
+                   GCancellable *cancellable)
 {
-       gchar *s;
+       GError *error = NULL;
 
-       s = g_alloca (depth+1);
-       memset (s, ' ', depth);
-       s[depth] = 0;
+       camel_store_noop_sync (CAMEL_STORE (object), cancellable, &error);
 
-       while (fi) {
-               printf("%suri: %s\n", s, fi->uri);
-               printf("%sfull_name: %s\n", s, fi->full_name);
-               printf("%sflags: %08x\n", s, fi->flags);
-               dump_fi (fi->child, depth+2);
-               fi = fi->next;
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
        }
 }
 
-/**
- * camel_store_get_folder_info_sync:
- * @store: a #CamelStore object
- * @top: the name of the folder to start from
- * @flags: various CAMEL_STORE_FOLDER_INFO_* flags to control behavior
- * @cancellable: optional #GCancellable object, or %NULL
- * @error: return location for a #GError, or %NULL
- *
- * This fetches information about the folder structure of @store,
- * starting with @top, and returns a tree of CamelFolderInfo
- * structures. If @flags includes %CAMEL_STORE_FOLDER_INFO_SUBSCRIBED,
- * only subscribed folders will be listed.   If the store doesn't support
- * subscriptions, then it will list all folders.  If @flags includes
- * %CAMEL_STORE_FOLDER_INFO_RECURSIVE, the returned tree will include
- * all levels of hierarchy below @top. If not, it will only include
- * the immediate subfolders of @top. If @flags includes
- * %CAMEL_STORE_FOLDER_INFO_FAST, the unread_message_count fields of
- * some or all of the structures may be set to %-1, if the store cannot
- * determine that information quickly.  If @flags includes
- * %CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL, don't include special virtual
+static void
+store_noop (CamelStore *store,
+            gint io_priority,
+            GCancellable *cancellable,
+            GAsyncReadyCallback callback,
+            gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (store), callback, user_data, store_noop);
+
+       g_simple_async_result_run_in_thread (
+               simple, store_noop_thread, io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+store_noop_finish (CamelStore *store,
+                   GAsyncResult *result,
+                   GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (store), store_noop), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
+camel_store_class_init (CamelStoreClass *class)
+{
+       GObjectClass *object_class;
+       CamelServiceClass *service_class;
+
+       g_type_class_add_private (class, sizeof (CamelStorePrivate));
+
+       object_class = G_OBJECT_CLASS (class);
+       object_class->finalize = store_finalize;
+       object_class->constructed = store_constructed;
+
+       service_class = CAMEL_SERVICE_CLASS (class);
+       service_class->construct = store_construct;
+
+       class->hash_folder_name = g_str_hash;
+       class->compare_folder_name = g_str_equal;
+       class->can_refresh_folder = store_can_refresh_folder;
+
+       class->get_inbox_folder_sync = store_get_inbox_folder_sync;
+       class->get_junk_folder_sync = store_get_junk_folder_sync;
+       class->get_trash_folder_sync = store_get_trash_folder_sync;
+       class->synchronize_sync = store_synchronize_sync;
+       class->noop_sync = store_noop_sync;
+
+       class->get_folder = store_get_folder;
+       class->get_folder_finish = store_get_folder_finish;
+       class->get_folder_info = store_get_folder_info;
+       class->get_folder_info_finish = store_get_folder_info_finish;
+       class->get_inbox_folder = store_get_inbox_folder;
+       class->get_inbox_folder_finish = store_get_inbox_folder_finish;
+       class->get_junk_folder = store_get_junk_folder;
+       class->get_junk_folder_finish = store_get_junk_folder_finish;
+       class->get_trash_folder = store_get_trash_folder;
+       class->get_trash_folder_finish = store_get_trash_folder_finish;
+       class->create_folder = store_create_folder;
+       class->create_folder_finish = store_create_folder_finish;
+       class->delete_folder = store_delete_folder;
+       class->delete_folder_finish = store_delete_folder_finish;
+       class->rename_folder = store_rename_folder;
+       class->rename_folder_finish = store_rename_folder_finish;
+       class->subscribe_folder = store_subscribe_folder;
+       class->subscribe_folder_finish = store_subscribe_folder_finish;
+       class->unsubscribe_folder = store_unsubscribe_folder;
+       class->unsubscribe_folder_finish = store_unsubscribe_folder_finish;
+       class->synchronize = store_synchronize;
+       class->synchronize_finish = store_synchronize_finish;
+       class->noop = store_noop;
+       class->noop_finish = store_noop_finish;
+
+       signals[FOLDER_CREATED] = g_signal_new (
+               "folder-created",
+               G_OBJECT_CLASS_TYPE (class),
+               G_SIGNAL_RUN_FIRST,
+               G_STRUCT_OFFSET (CamelStoreClass, folder_created),
+               NULL, NULL,
+               g_cclosure_marshal_VOID__POINTER,
+               G_TYPE_NONE, 1,
+               G_TYPE_POINTER);
+
+       signals[FOLDER_DELETED] = g_signal_new (
+               "folder-deleted",
+               G_OBJECT_CLASS_TYPE (class),
+               G_SIGNAL_RUN_FIRST,
+               G_STRUCT_OFFSET (CamelStoreClass, folder_deleted),
+               NULL, NULL,
+               g_cclosure_marshal_VOID__POINTER,
+               G_TYPE_NONE, 1,
+               G_TYPE_POINTER);
+
+       signals[FOLDER_OPENED] = g_signal_new (
+               "folder-opened",
+               G_OBJECT_CLASS_TYPE (class),
+               G_SIGNAL_RUN_FIRST,
+               G_STRUCT_OFFSET (CamelStoreClass, folder_opened),
+               NULL, NULL,
+               g_cclosure_marshal_VOID__OBJECT,
+               G_TYPE_NONE, 1,
+               CAMEL_TYPE_FOLDER);
+
+       signals[FOLDER_RENAMED] = g_signal_new (
+               "folder-renamed",
+               G_OBJECT_CLASS_TYPE (class),
+               G_SIGNAL_RUN_FIRST,
+               G_STRUCT_OFFSET (CamelStoreClass, folder_renamed),
+               NULL, NULL,
+               camel_marshal_VOID__STRING_POINTER,
+               G_TYPE_NONE, 2,
+               G_TYPE_STRING,
+               G_TYPE_POINTER);
+
+       signals[FOLDER_SUBSCRIBED] = g_signal_new (
+               "folder-subscribed",
+               G_OBJECT_CLASS_TYPE (class),
+               G_SIGNAL_RUN_FIRST,
+               G_STRUCT_OFFSET (CamelStoreClass, folder_subscribed),
+               NULL, NULL,
+               g_cclosure_marshal_VOID__POINTER,
+               G_TYPE_NONE, 1,
+               G_TYPE_POINTER);
+
+       signals[FOLDER_UNSUBSCRIBED] = g_signal_new (
+               "folder-unsubscribed",
+               G_OBJECT_CLASS_TYPE (class),
+               G_SIGNAL_RUN_FIRST,
+               G_STRUCT_OFFSET (CamelStoreClass, folder_unsubscribed),
+               NULL, NULL,
+               g_cclosure_marshal_VOID__POINTER,
+               G_TYPE_NONE, 1,
+               G_TYPE_POINTER);
+}
+
+static void
+camel_store_init (CamelStore *store)
+{
+       store->priv = CAMEL_STORE_GET_PRIVATE (store);
+
+       /* set vtrash and vjunk on by default */
+       store->flags = CAMEL_STORE_VTRASH | CAMEL_STORE_VJUNK;
+       store->mode = CAMEL_STORE_READ | CAMEL_STORE_WRITE;
+
+       g_static_rec_mutex_init (&store->priv->folder_lock);
+}
+
+GQuark
+camel_store_error_quark (void)
+{
+       static GQuark quark = 0;
+
+       if (G_UNLIKELY (quark == 0)) {
+               const gchar *string = "camel-store-error-quark";
+               quark = g_quark_from_static_string (string);
+       }
+
+       return quark;
+}
+
+/* deletes folder/removes it from the folder cache, if it's there */
+static void
+cs_delete_cached_folder (CamelStore *store,
+                         const gchar *folder_name)
+{
+       CamelFolder *folder;
+
+       if (store->folders
+           && (folder = camel_object_bag_get (store->folders, folder_name))) {
+               CamelVeeFolder *vfolder;
+
+               if ((store->flags & CAMEL_STORE_VTRASH)
+                   && (vfolder = camel_object_bag_get(store->folders, CAMEL_VTRASH_NAME))) {
+                       camel_vee_folder_remove_folder (vfolder, folder);
+                       g_object_unref (vfolder);
+               }
+
+               if ((store->flags & CAMEL_STORE_VJUNK)
+                   && (vfolder = camel_object_bag_get(store->folders, CAMEL_VJUNK_NAME))) {
+                       camel_vee_folder_remove_folder(vfolder, folder);
+                       g_object_unref (vfolder);
+               }
+
+               camel_folder_delete (folder);
+
+               camel_object_bag_remove (store->folders, folder);
+               g_object_unref (folder);
+       }
+}
+
+/**
+ * camel_store_folder_created:
+ * @store: a #CamelStore
+ * @info: information about the created folder
+ *
+ * Emits the #CamelStore::folder-created signal.
+ *
+ * This function is only intended for Camel providers.
+ *
+ * Since: 2.32
+ **/
+void
+camel_store_folder_created (CamelStore *store,
+                            CamelFolderInfo *info)
+{
+       g_return_if_fail (CAMEL_STORE (store));
+       g_return_if_fail (info != NULL);
+
+       g_signal_emit (store, signals[FOLDER_CREATED], 0, info);
+}
+
+/**
+ * camel_store_folder_deleted:
+ * @store: a #CamelStore
+ * @info: information about the deleted folder
+ *
+ * Emits the #CamelStore::folder-deleted signal.
+ *
+ * This function is only intended for Camel providers.
+ *
+ * Since: 2.32
+ **/
+void
+camel_store_folder_deleted (CamelStore *store,
+                            CamelFolderInfo *info)
+{
+       g_return_if_fail (CAMEL_STORE (store));
+       g_return_if_fail (info != NULL);
+
+       g_signal_emit (store, signals[FOLDER_DELETED], 0, info);
+}
+
+/**
+ * camel_store_folder_renamed:
+ * @store: a #CamelStore
+ * @old_name: the old name of the folder
+ * @info: information about the renamed folder
+ *
+ * Emits the #CamelStore::folder-renamed signal.
+ *
+ * This function is only intended for Camel providers.
+ *
+ * Since: 2.32
+ **/
+void
+camel_store_folder_renamed (CamelStore *store,
+                            const gchar *old_name,
+                            CamelFolderInfo *info)
+{
+       g_return_if_fail (CAMEL_STORE (store));
+       g_return_if_fail (old_name != NULL);
+       g_return_if_fail (info != NULL);
+
+       g_signal_emit (store, signals[FOLDER_RENAMED], 0, old_name, info);
+}
+
+/**
+ * camel_store_folder_subscribed:
+ * @store: a #CamelStore
+ * @info: information about the subscribed folder
+ *
+ * Emits the #CamelStore::folder-subscribed signal.
+ *
+ * This function is only intended for Camel providers.
+ *
+ * Since: 2.32
+ **/
+void
+camel_store_folder_subscribed (CamelStore *store,
+                               CamelFolderInfo *info)
+{
+       g_return_if_fail (CAMEL_STORE (store));
+       g_return_if_fail (info != NULL);
+
+       g_signal_emit (store, signals[FOLDER_SUBSCRIBED], 0, info);
+}
+
+/**
+ * camel_store_folder_unsubscribed:
+ * @store: a #CamelStore
+ * @info: information about the unsubscribed folder
+ *
+ * Emits the #CamelStore::folder-unsubscribed signal.
+ *
+ * This function is only intended for Camel providers.
+ *
+ * Since: 2.32
+ **/
+void
+camel_store_folder_unsubscribed (CamelStore *store,
+                                 CamelFolderInfo *info)
+{
+       g_return_if_fail (CAMEL_STORE (store));
+       g_return_if_fail (info != NULL);
+
+       g_signal_emit (store, signals[FOLDER_UNSUBSCRIBED], 0, info);
+}
+
+static void
+add_special_info (CamelStore *store,
+                  CamelFolderInfo *info,
+                  const gchar *name,
+                  const gchar *translated,
+                  gboolean unread_count,
+                  guint32 flags)
+{
+       CamelFolderInfo *fi, *vinfo, *parent;
+       gchar *uri, *path;
+       CamelURL *url;
+
+       g_return_if_fail (info != NULL);
+
+       parent = NULL;
+       for (fi = info; fi; fi = fi->next) {
+               if (!strcmp (fi->full_name, name))
+                       break;
+               parent = fi;
+       }
+
+       /* create our vTrash/vJunk URL */
+       url = camel_url_new (info->uri, NULL);
+       if (((CamelService *) store)->provider->url_flags & CAMEL_URL_FRAGMENT_IS_PATH) {
+               camel_url_set_fragment (url, name);
+       } else {
+               path = g_strdup_printf ("/%s", name);
+               camel_url_set_path (url, path);
+               g_free (path);
+       }
+
+       uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL);
+       camel_url_free (url);
+
+       if (fi) {
+               /* We're going to replace the physical Trash/Junk folder with our vTrash/vJunk folder */
+               vinfo = fi;
+               g_free (vinfo->full_name);
+               g_free (vinfo->name);
+               g_free (vinfo->uri);
+       } else {
+               /* There wasn't a Trash/Junk folder so create a new folder entry */
+               vinfo = camel_folder_info_new ();
+
+               g_assert (parent != NULL);
+
+               vinfo->flags |= CAMEL_FOLDER_NOINFERIORS | CAMEL_FOLDER_SUBSCRIBED;
+
+               /* link it into the right spot */
+               vinfo->next = parent->next;
+               parent->next = vinfo;
+       }
+
+       /* Fill in the new fields */
+       vinfo->flags |= flags;
+       vinfo->full_name = g_strdup (name);
+       vinfo->name = g_strdup (translated);
+       vinfo->uri = uri;
+       if (!unread_count)
+               vinfo->unread = -1;
+}
+
+static void
+dump_fi (CamelFolderInfo *fi, gint depth)
+{
+       gchar *s;
+
+       s = g_alloca (depth+1);
+       memset (s, ' ', depth);
+       s[depth] = 0;
+
+       while (fi) {
+               printf("%suri: %s\n", s, fi->uri);
+               printf("%sfull_name: %s\n", s, fi->full_name);
+               printf("%sflags: %08x\n", s, fi->flags);
+               dump_fi (fi->child, depth+2);
+               fi = fi->next;
+       }
+}
+
+/**
+ * camel_store_free_folder_info:
+ * @store: a #CamelStore
+ * @fi: a #CamelFolderInfo as gotten via #camel_store_get_folder_info
+ *
+ * Frees the data returned by #camel_store_get_folder_info. If @fi is %NULL,
+ * nothing is done, the routine simply returns.
+ **/
+void
+camel_store_free_folder_info (CamelStore *store,
+                              CamelFolderInfo *fi)
+{
+       CamelStoreClass *class;
+
+       g_return_if_fail (CAMEL_IS_STORE (store));
+
+       if (fi == NULL)
+               return;
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->free_folder_info != NULL);
+
+       class->free_folder_info (store, fi);
+}
+
+/**
+ * camel_store_free_folder_info_full:
+ * @store: a #CamelStore
+ * @fi: a #CamelFolderInfo as gotten via #camel_store_get_folder_info
+ *
+ * An implementation for #CamelStore::free_folder_info. Frees all
+ * of the data.
+ **/
+void
+camel_store_free_folder_info_full (CamelStore *store,
+                                   CamelFolderInfo *fi)
+{
+       camel_folder_info_free (fi);
+}
+
+/**
+ * camel_store_free_folder_info_nop:
+ * @store: a #CamelStore
+ * @fi: a #CamelFolderInfo as gotten via #camel_store_get_folder_info
+ *
+ * An implementation for #CamelStore::free_folder_info. Does nothing.
+ **/
+void
+camel_store_free_folder_info_nop (CamelStore *store,
+                                  CamelFolderInfo *fi)
+{
+       ;
+}
+
+/**
+ * camel_folder_info_free:
+ * @fi: a #CamelFolderInfo
+ *
+ * Frees @fi.
+ **/
+void
+camel_folder_info_free (CamelFolderInfo *fi)
+{
+       if (fi != NULL) {
+               camel_folder_info_free (fi->next);
+               camel_folder_info_free (fi->child);
+               g_free (fi->name);
+               g_free (fi->full_name);
+               g_free (fi->uri);
+               g_slice_free (CamelFolderInfo, fi);
+       }
+}
+
+/**
+ * camel_folder_info_new:
+ *
+ * Returns: a new empty CamelFolderInfo instance
+ *
+ * Since: 2.22
+ **/
+CamelFolderInfo *
+camel_folder_info_new (void)
+{
+       return g_slice_new0 (CamelFolderInfo);
+}
+
+static gint
+folder_info_cmp (gconstpointer ap,
+                 gconstpointer bp)
+{
+       const CamelFolderInfo *a = ((CamelFolderInfo **)ap)[0];
+       const CamelFolderInfo *b = ((CamelFolderInfo **)bp)[0];
+
+       return strcmp (a->full_name, b->full_name);
+}
+
+/**
+ * camel_folder_info_build:
+ * @folders: an array of #CamelFolderInfo
+ * @namespace: an ignorable prefix on the folder names
+ * @separator: the hieararchy separator character
+ * @short_names: %TRUE if the (short) name of a folder is the part after
+ * the last @separator in the full name. %FALSE if it is the full name.
+ *
+ * This takes an array of folders and attaches them together according
+ * to the hierarchy described by their full_names and @separator. If
+ * @namespace is non-%NULL, then it will be ignored as a full_name
+ * prefix, for purposes of comparison. If necessary,
+ * #camel_folder_info_build will create additional #CamelFolderInfo with
+ * %NULL urls to fill in gaps in the tree. The value of @short_names
+ * is used in constructing the names of these intermediate folders.
+ *
+ * NOTE: This is deprected, do not use this.
+ * FIXME: remove this/move it to imap, which is the only user of it now.
+ *
+ * Returns: the top level of the tree of linked folder info.
+ **/
+CamelFolderInfo *
+camel_folder_info_build (GPtrArray *folders,
+                         const gchar *namespace,
+                         gchar separator,
+                         gboolean short_names)
+{
+       CamelFolderInfo *fi, *pfi, *top = NULL, *tail = NULL;
+       GHashTable *hash;
+       gchar *p, *pname;
+       gint i, nlen;
+
+       if (!namespace)
+               namespace = "";
+       nlen = strlen (namespace);
+
+       qsort (folders->pdata, folders->len, sizeof (folders->pdata[0]), folder_info_cmp);
+
+       /* Hash the folders. */
+       hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+       for (i = 0; i < folders->len; i++) {
+               fi = folders->pdata[i];
+               g_hash_table_insert (hash, g_strdup (fi->full_name), fi);
+       }
+
+       /* Now find parents. */
+       for (i = 0; i < folders->len; i++) {
+               fi = folders->pdata[i];
+               if (!strncmp (namespace, fi->full_name, nlen)
+                   && (p = strrchr (fi->full_name+nlen, separator))) {
+                       pname = g_strndup (fi->full_name, p - fi->full_name);
+                       pfi = g_hash_table_lookup (hash, pname);
+                       if (pfi) {
+                               g_free (pname);
+                       } else {
+                               /* we are missing a folder in the heirarchy so
+                                  create a fake folder node */
+                               const gchar *path;
+                               CamelURL *url;
+                               gchar *sep;
+
+                               pfi = camel_folder_info_new ();
+                               if (short_names) {
+                                       pfi->name = strrchr (pname, separator);
+                                       if (pfi->name)
+                                               pfi->name = g_strdup (pfi->name + 1);
+                                       else
+                                               pfi->name = g_strdup (pname);
+                               } else
+                                       pfi->name = g_strdup (pname);
+
+                               url = camel_url_new (fi->uri, NULL);
+                               if (url->fragment)
+                                       path = url->fragment;
+                               else
+                                       path = url->path + 1;
+
+                               sep = strrchr (path, separator);
+                               if (sep)
+                                       *sep = '\0';
+                               else {
+                                       d(g_warning ("huh, no \"%c\" in \"%s\"?", separator, fi->uri));
+                               }
+
+                               pfi->full_name = g_strdup (path);
+
+                               /* since this is a "fake" folder node, it is not selectable */
+                               camel_url_set_param (url, "noselect", "yes");
+                               pfi->uri = camel_url_to_string (url, 0);
+                               camel_url_free (url);
+
+                               g_hash_table_insert (hash, pname, pfi);
+                               g_ptr_array_add (folders, pfi);
+                       }
+                       tail = (CamelFolderInfo *)&pfi->child;
+                       while (tail->next)
+                               tail = tail->next;
+                       tail->next = fi;
+                       fi->parent = pfi;
+               } else if (!top)
+                       top = fi;
+       }
+       g_hash_table_destroy (hash);
+
+       /* Link together the top-level folders */
+       tail = top;
+       for (i = 0; i < folders->len; i++) {
+               fi = folders->pdata[i];
+
+               if (fi->child)
+                       fi->flags &= ~CAMEL_FOLDER_NOCHILDREN;
+
+               if (fi->parent || fi == top)
+                       continue;
+               if (tail == NULL) {
+                       tail = fi;
+                       top = fi;
+               } else {
+                       tail->next = fi;
+                       tail = fi;
+               }
+       }
+
+       return top;
+}
+
+static CamelFolderInfo *
+folder_info_clone_rec (CamelFolderInfo *fi,
+                       CamelFolderInfo *parent)
+{
+       CamelFolderInfo *info;
+
+       info = camel_folder_info_new ();
+       info->parent = parent;
+       info->uri = g_strdup (fi->uri);
+       info->name = g_strdup (fi->name);
+       info->full_name = g_strdup (fi->full_name);
+       info->unread = fi->unread;
+       info->flags = fi->flags;
+
+       if (fi->next)
+               info->next = folder_info_clone_rec (fi->next, parent);
+       else
+               info->next = NULL;
+
+       if (fi->child)
+               info->child = folder_info_clone_rec (fi->child, info);
+       else
+               info->child = NULL;
+
+       return info;
+}
+
+/**
+ * camel_folder_info_clone:
+ * @fi: a #CamelFolderInfo
+ *
+ * Clones @fi recursively.
+ *
+ * Returns: the cloned #CamelFolderInfo tree.
+ **/
+CamelFolderInfo *
+camel_folder_info_clone (CamelFolderInfo *fi)
+{
+       if (fi == NULL)
+               return NULL;
+
+       return folder_info_clone_rec (fi, NULL);
+}
+
+/**
+ * camel_store_supports_subscriptions:
+ * @store: a #CamelStore
+ *
+ * Get whether or not @store supports subscriptions to folders.
+ *
+ * Returns: %TRUE if folder subscriptions are supported or %FALSE otherwise
+ **/
+gboolean
+camel_store_supports_subscriptions (CamelStore *store)
+{
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+
+       return (store->flags & CAMEL_STORE_SUBSCRIPTIONS);
+}
+
+/**
+ * camel_store_folder_is_subscribed:
+ * @store: a #CamelStore
+ * @folder_name: full path of the folder
+ *
+ * Find out if a folder has been subscribed to.
+ *
+ * Returns: %TRUE if the folder has been subscribed to or %FALSE otherwise
+ **/
+gboolean
+camel_store_folder_is_subscribed (CamelStore *store,
+                                  const gchar *folder_name)
+{
+       CamelStoreClass *class;
+       gboolean is_subscribed;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (folder_name != NULL, FALSE);
+       g_return_val_if_fail (store->flags & CAMEL_STORE_SUBSCRIPTIONS, FALSE);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->folder_is_subscribed != NULL, FALSE);
+
+       camel_store_lock (store, CAMEL_STORE_FOLDER_LOCK);
+
+       is_subscribed = class->folder_is_subscribed (store, folder_name);
+
+       camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+
+       return is_subscribed;
+}
+
+/**
+ * camel_store_folder_uri_equal:
+ * @store: a #CamelStore
+ * @uri0: a folder uri
+ * @uri1: another folder uri
+ *
+ * Compares two folder uris to check that they are equal.
+ *
+ * Returns: %TRUE if they are equal or %FALSE otherwise
+ **/
+gint
+camel_store_folder_uri_equal (CamelStore *store,
+                              const gchar *uri0,
+                              const gchar *uri1)
+{
+       CamelStoreClass *class;
+       CamelProvider *provider;
+       CamelURL *url0, *url1;
+       gint equal;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (uri0 && uri1, FALSE);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->compare_folder_name != NULL, FALSE);
+
+       provider = ((CamelService *) store)->provider;
+
+       if (!(url0 = camel_url_new (uri0, NULL)))
+               return FALSE;
+
+       if (!(url1 = camel_url_new (uri1, NULL))) {
+               camel_url_free (url0);
+               return FALSE;
+       }
+
+       if ((equal = provider->url_equal (url0, url1))) {
+               const gchar *name0, *name1;
+
+               if (provider->url_flags & CAMEL_URL_FRAGMENT_IS_PATH) {
+                       name0 = url0->fragment;
+                       name1 = url1->fragment;
+               } else {
+                       name0 = url0->path && url0->path[0] == '/' ? url0->path + 1 : url0->path;
+                       name1 = url1->path && url1->path[0] == '/' ? url1->path + 1 : url1->path;
+               }
+
+               if (name0 == NULL)
+                       g_warning("URI is badly formed, missing folder name: %s", uri0);
+
+               if (name1 == NULL)
+                       g_warning("URI is badly formed, missing folder name: %s", uri1);
+
+               equal = name0 && name1 && class->compare_folder_name (name0, name1);
+       }
+
+       camel_url_free (url0);
+       camel_url_free (url1);
+
+       return equal;
+}
+
+/**
+ * camel_store_can_refresh_folder
+ * @store: a #CamelStore
+ * @info: a #CamelFolderInfo
+ * @error: return location for a #GError, or %NULL
+ *
+ * Returns if this folder (param info) should be checked for new mail or not.
+ * It should not look into sub infos (info->child) or next infos, it should
+ * return value only for the actual folder info.
+ * Default behavior is that all Inbox folders are intended to be refreshed.
+ *
+ * Returns: whether folder should be checked for new mails
+ *
+ * Since: 2.22
+ **/
+gboolean
+camel_store_can_refresh_folder (CamelStore *store,
+                                CamelFolderInfo *info,
+                                GError **error)
+{
+       CamelStoreClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (info != NULL, FALSE);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->can_refresh_folder != NULL, FALSE);
+
+       return class->can_refresh_folder (store, info, error);
+}
+
+/**
+ * camel_store_lock:
+ * @store: a #CamelStore
+ * @lock: lock type to lock
+ *
+ * Locks #store's #lock. Unlock it with camel_store_unlock().
+ *
+ * Since: 2.32
+ **/
+void
+camel_store_lock (CamelStore *store,
+                  CamelStoreLock lock)
+{
+       g_return_if_fail (CAMEL_IS_STORE (store));
+
+       switch (lock) {
+               case CAMEL_STORE_FOLDER_LOCK:
+                       g_static_rec_mutex_lock (&store->priv->folder_lock);
+                       break;
+               default:
+                       g_return_if_reached ();
+       }
+}
+
+/**
+ * camel_store_unlock:
+ * @store: a #CamelStore
+ * @lock: lock type to unlock
+ *
+ * Unlocks #store's #lock, previously locked with camel_store_lock().
+ *
+ * Since: 2.32
+ **/
+void
+camel_store_unlock (CamelStore *store,
+                    CamelStoreLock lock)
+{
+       g_return_if_fail (CAMEL_IS_STORE (store));
+
+       switch (lock) {
+               case CAMEL_STORE_FOLDER_LOCK:
+                       g_static_rec_mutex_unlock (&store->priv->folder_lock);
+                       break;
+               default:
+                       g_return_if_reached ();
+       }
+}
+
+/**
+ * camel_store_get_folder_sync:
+ * @store: a #CamelStore
+ * @folder_name: name of the folder to get
+ * @flags: folder flags (create, save body index, etc)
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets a specific folder object from @store by name.
+ *
+ * Returns: the requested #CamelFolder object, or %NULL on error
+ *
+ * Since: 2.34
+ **/
+CamelFolder *
+camel_store_get_folder_sync (CamelStore *store,
+                             const gchar *folder_name,
+                             guint32 flags,
+                             GCancellable *cancellable,
+                             GError **error)
+{
+       CamelStoreClass *class;
+       CamelFolder *folder = NULL;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+       g_return_val_if_fail (folder_name != NULL, NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+
+       /* O_EXCL doesn't make sense if we aren't requesting to also create the folder if it doesn't exist */
+       if (!(flags & CAMEL_STORE_FOLDER_CREATE))
+               flags &= ~CAMEL_STORE_FOLDER_EXCL;
+
+       if (store->folders) {
+               /* Try cache first. */
+               folder = camel_object_bag_reserve (store->folders, folder_name);
+               if (folder && (flags & CAMEL_STORE_FOLDER_EXCL)) {
+                       g_set_error (
+                               error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+                               _("Cannot create folder '%s': folder exists"),
+                               folder_name);
+                        camel_object_bag_abort (store->folders, folder_name);
+                       g_object_unref (folder);
+                       return NULL;
+               }
+       }
+
+       if (!folder) {
+
+               if (flags & CAMEL_STORE_IS_MIGRATING) {
+                       if ((store->flags & CAMEL_STORE_VTRASH) && strcmp (folder_name, CAMEL_VTRASH_NAME) == 0) {
+                               if (store->folders)
+                                       camel_object_bag_abort (store->folders, folder_name);
+                               return NULL;
+                       }
+
+                       if ((store->flags & CAMEL_STORE_VJUNK) && strcmp (folder_name, CAMEL_VJUNK_NAME) == 0) {
+                               if (store->folders)
+                                               camel_object_bag_abort (store->folders, folder_name);
+                               return NULL;
+                       }
+               }
+
+               if ((store->flags & CAMEL_STORE_VTRASH) && strcmp(folder_name, CAMEL_VTRASH_NAME) == 0) {
+                       folder = class->get_trash_folder_sync (store, cancellable, error);
+                       CAMEL_CHECK_GERROR (store, get_trash_folder_sync, folder != NULL, error);
+               } else if ((store->flags & CAMEL_STORE_VJUNK) && strcmp(folder_name, CAMEL_VJUNK_NAME) == 0) {
+                       folder = class->get_junk_folder_sync (store, cancellable, error);
+                       CAMEL_CHECK_GERROR (store, get_junk_folder_sync, folder != NULL, error);
+               } else {
+                       folder = class->get_folder_sync (
+                               store, folder_name, flags, cancellable, error);
+                       CAMEL_CHECK_GERROR (store, get_folder_sync, folder != NULL, error);
+
+                       if (folder) {
+                               CamelVeeFolder *vfolder;
+
+                               if ((store->flags & CAMEL_STORE_VTRASH)
+                                   && (vfolder = camel_object_bag_get (store->folders, CAMEL_VTRASH_NAME))) {
+                                       camel_vee_folder_add_folder (vfolder, folder);
+                                       g_object_unref (vfolder);
+                               }
+
+                               if ((store->flags & CAMEL_STORE_VJUNK)
+                                   && (vfolder = camel_object_bag_get (store->folders, CAMEL_VJUNK_NAME))) {
+                                       camel_vee_folder_add_folder (vfolder, folder);
+                                       g_object_unref (vfolder);
+                               }
+                       }
+               }
+
+               if (store->folders) {
+                       if (folder)
+                               camel_object_bag_add (store->folders, folder_name, folder);
+                       else
+                               camel_object_bag_abort (store->folders, folder_name);
+               }
+
+               if (folder)
+                       g_signal_emit (store, signals[FOLDER_OPENED], 0, folder);
+       }
+
+       return folder;
+}
+
+/**
+ * camel_store_get_folder:
+ * @store: a #CamelStore
+ * @folder_name: name of the folder to get
+ * @flags: folder flags (create, save body index, etc)
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously gets a specific folder object from @store by name.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_store_get_folder_finish() to get the result of the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_store_get_folder (CamelStore *store,
+                        const gchar *folder_name,
+                        guint32 flags,
+                        gint io_priority,
+                        GCancellable *cancellable,
+                        GAsyncReadyCallback callback,
+                        gpointer user_data)
+{
+       CamelStoreClass *class;
+
+       g_return_if_fail (CAMEL_IS_STORE (store));
+       g_return_if_fail (folder_name != NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->get_folder != NULL);
+
+       class->get_folder (
+               store, folder_name, flags, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_store_get_folder_finish:
+ * @store: a #CamelStore
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_store_get_folder().
+ *
+ * Returns: the requested #CamelFolder object, or %NULL on error
+ *
+ * Since: 2.34
+ **/
+CamelFolder *
+camel_store_get_folder_finish (CamelStore *store,
+                               GAsyncResult *result,
+                               GError **error)
+{
+       CamelStoreClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->get_folder_finish != NULL, NULL);
+
+       return class->get_folder_finish (store, result, error);
+}
+
+/**
+ * camel_store_get_folder_info_sync:
+ * @store: a #CamelStore
+ * @top: the name of the folder to start from
+ * @flags: various CAMEL_STORE_FOLDER_INFO_* flags to control behavior
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * This fetches information about the folder structure of @store,
+ * starting with @top, and returns a tree of #CamelFolderInfo
+ * structures. If @flags includes %CAMEL_STORE_FOLDER_INFO_SUBSCRIBED,
+ * only subscribed folders will be listed.   If the store doesn't support
+ * subscriptions, then it will list all folders.  If @flags includes
+ * %CAMEL_STORE_FOLDER_INFO_RECURSIVE, the returned tree will include
+ * all levels of hierarchy below @top. If not, it will only include
+ * the immediate subfolders of @top. If @flags includes
+ * %CAMEL_STORE_FOLDER_INFO_FAST, the unread_message_count fields of
+ * some or all of the structures may be set to %-1, if the store cannot
+ * determine that information quickly.  If @flags includes
+ * %CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL, don't include special virtual
  * folders (such as vTrash or vJunk).
  *
- * The CAMEL_STORE_FOLDER_INFO_FAST flag should be considered
- * deprecated; most backends will behave the same whether it is
- * supplied or not.  The only guaranteed way to get updated folder
- * counts is to both open the folder and invoke refresh_info() it.
+ * The returned #CamelFolderInfo tree should be freed with
+ * camel_store_free_folder_info().
+ *
+ * The CAMEL_STORE_FOLDER_INFO_FAST flag should be considered
+ * deprecated; most backends will behave the same whether it is
+ * supplied or not.  The only guaranteed way to get updated folder
+ * counts is to both open the folder and invoke refresh_info() it.
+ *
+ * Returns: a #CamelFolderInfo tree, or %NULL on error
+ *
+ * Since: 2.34
+ **/
+CamelFolderInfo *
+camel_store_get_folder_info_sync (CamelStore *store,
+                                  const gchar *top,
+                                  guint32 flags,
+                                  GCancellable *cancellable,
+                                  GError **error)
+{
+       CamelStoreClass *class;
+       CamelFolderInfo *info;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->get_folder_info_sync != NULL, NULL);
+
+       info = class->get_folder_info_sync (
+               store, top, flags, cancellable, error);
+       if (!(flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED))
+               CAMEL_CHECK_GERROR (
+                       store, get_folder_info_sync, info != NULL, error);
+
+       if (info && (top == NULL || *top == '\0') && (flags & CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL) == 0) {
+               if (info->uri && (store->flags & CAMEL_STORE_VTRASH))
+                       /* the name of the Trash folder, used for deleted messages */
+                       add_special_info (store, info, CAMEL_VTRASH_NAME, _("Trash"), FALSE, CAMEL_FOLDER_VIRTUAL|CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_VTRASH|CAMEL_FOLDER_TYPE_TRASH);
+               if (info->uri && (store->flags & CAMEL_STORE_VJUNK))
+                       /* the name of the Junk folder, used for spam messages */
+                       add_special_info (store, info, CAMEL_VJUNK_NAME, _("Junk"), TRUE, CAMEL_FOLDER_VIRTUAL|CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_VTRASH|CAMEL_FOLDER_TYPE_JUNK);
+       }
+
+       if (camel_debug_start("store:folder_info")) {
+               gchar *url = camel_url_to_string (((CamelService *)store)->url, CAMEL_URL_HIDE_ALL);
+               printf("Get folder info(%p:%s, '%s') =\n", (gpointer) store, url, top?top:"<null>");
+               g_free (url);
+               dump_fi (info, 2);
+               camel_debug_end ();
+       }
+
+       return info;
+}
+
+/**
+ * camel_store_get_folder_info:
+ * @store: a #CamelStore
+ * @top: the name of the folder to start from
+ * @flags: various CAMEL_STORE_FOLDER_INFO_* flags to control behavior
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously fetches information about the folder structure of @store,
+ * starting with @top.  For details of the behavior, see
+ * camel_store_get_folder_info_sync().
+ *
+ * When the operation is finished, @callback will be called.  You can
+ * then call camel_store_get_folder_info_finish() to get the result of
+ * the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_store_get_folder_info (CamelStore *store,
+                             const gchar *top,
+                             guint32 flags,
+                             gint io_priority,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
+{
+       CamelStoreClass *class;
+
+       g_return_if_fail (CAMEL_IS_STORE (store));
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->get_folder_info != NULL);
+
+       class->get_folder_info (
+               store, top, flags, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_store_get_folder_info_finish:
+ * @store: a #CamelStore
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_store_get_folder_info().
+ * The returned #CamelFolderInfo tree should be freed with
+ * camel_store_free_folder_info().
+ *
+ * Returns: a #CamelFolderInfo tree, or %NULL on error
+ *
+ * Since: 2.34
+ **/
+CamelFolderInfo *
+camel_store_get_folder_info_finish (CamelStore *store,
+                                    GAsyncResult *result,
+                                    GError **error)
+{
+       CamelStoreClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->get_folder_info_finish != NULL, NULL);
+
+       return class->get_folder_info_finish (store, result, error);
+}
+
+/**
+ * camel_store_get_inbox_folder_sync:
+ * @store: a #CamelStore
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets the folder in @store into which new mail is delivered.
+ *
+ * Returns: the inbox folder for @store, or %NULL on error or if no such
+ * folder exists
+ *
+ * Since: 2.34
+ **/
+CamelFolder *
+camel_store_get_inbox_folder_sync (CamelStore *store,
+                                   GCancellable *cancellable,
+                                   GError **error)
+{
+       CamelStoreClass *class;
+       CamelFolder *folder;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->get_inbox_folder_sync != NULL, NULL);
+
+       camel_store_lock (store, CAMEL_STORE_FOLDER_LOCK);
+
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+               return NULL;
+       }
+
+       folder = class->get_inbox_folder_sync (store, cancellable, error);
+       CAMEL_CHECK_GERROR (
+               store, get_inbox_folder_sync, folder != NULL, error);
+
+       camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+
+       return folder;
+}
+
+/**
+ * camel_store_get_inbox_folder:
+ * @store: a #CamelStore
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously gets the folder in @store into which new mail is delivered.
+ *
+ * When the operation is finished, @callback will be called.  You can
+ * then call camel_store_get_inbox_folder_finish() to get the result of
+ * the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_store_get_inbox_folder (CamelStore *store,
+                              gint io_priority,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
+{
+       CamelStoreClass *class;
+
+       g_return_if_fail (CAMEL_IS_STORE (store));
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->get_inbox_folder != NULL);
+
+       class->get_inbox_folder (
+               store, io_priority, cancellable, callback, user_data);
+}
+
+/**
+ * camel_store_get_inbox_folder_finish:
+ * @store: a #CamelStore
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_store_get_inbox_folder().
+ *
+ * Returns: the inbox folder for @store, or %NULL on error or if no such
+ * folder exists
+ *
+ * Since: 2.34
+ **/
+CamelFolder *
+camel_store_get_inbox_folder_finish (CamelStore *store,
+                                     GAsyncResult *result,
+                                     GError **error)
+{
+       CamelStoreClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->get_inbox_folder_finish != NULL, NULL);
+
+       return class->get_inbox_folder_finish (store, result, error);
+}
+
+/**
+ * camel_store_get_junk_folder_sync:
+ * @store: a #CamelStore
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets the folder in @store into which junk is delivered.
+ *
+ * Returns: the junk folder for @store, or %NULL on error or if no such
+ * folder exists
+ *
+ * Since: 2.34
+ **/
+CamelFolder *
+camel_store_get_junk_folder_sync (CamelStore *store,
+                                  GCancellable *cancellable,
+                                  GError **error)
+{
+       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+
+       if ((store->flags & CAMEL_STORE_VJUNK) == 0) {
+               CamelStoreClass *class;
+               CamelFolder *folder;
+
+               class = CAMEL_STORE_GET_CLASS (store);
+               g_return_val_if_fail (class->get_junk_folder_sync != NULL, NULL);
+
+               folder = class->get_junk_folder_sync (store, cancellable, error);
+               CAMEL_CHECK_GERROR (
+                       store, get_junk_folder_sync, folder != NULL, error);
+
+               return folder;
+       }
+
+       return camel_store_get_folder_sync (
+               store, CAMEL_VJUNK_NAME, 0, cancellable, error);
+}
+
+/**
+ * camel_store_get_junk_folder:
+ * @store: a #CamelStore
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously gets the folder in @store into which junk is delivered.
+ *
+ * When the operation is finished, @callback will be called.  You can
+ * then call camel_store_get_junk_folder_finish() to get the result of
+ * the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_store_get_junk_folder (CamelStore *store,
+                             gint io_priority,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
+{
+       CamelStoreClass *class;
+
+       g_return_if_fail (CAMEL_IS_STORE (store));
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->get_junk_folder != NULL);
+
+       class->get_junk_folder (
+               store, io_priority, cancellable, callback, user_data);
+}
+
+/**
+ * camel_store_get_junk_folder_finish:
+ * @store: a #CamelStore
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_store_get_junk_folder().
+ *
+ * Returns: the junk folder for @store, or %NULL on error or if no such
+ * folder exists
+ *
+ * Since: 2.34
+ **/
+CamelFolder *
+camel_store_get_junk_folder_finish (CamelStore *store,
+                                    GAsyncResult *result,
+                                    GError **error)
+{
+       CamelStoreClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->get_junk_folder_finish != NULL, NULL);
+
+       return class->get_junk_folder_finish (store, result, error);
+}
+
+/**
+ * camel_store_get_trash_folder_sync:
+ * @store: a #CamelStore
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets the folder in @store into which trash is delivered.
+ *
+ * Returns: the trash folder for @store, or %NULL on error or if no such
+ * folder exists
+ *
+ * Since: 2.34
+ **/
+CamelFolder *
+camel_store_get_trash_folder_sync (CamelStore *store,
+                                   GCancellable *cancellable,
+                                   GError **error)
+{
+       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+
+       if ((store->flags & CAMEL_STORE_VTRASH) == 0) {
+               CamelStoreClass *class;
+               CamelFolder *folder;
+
+               class = CAMEL_STORE_GET_CLASS (store);
+               g_return_val_if_fail (class->get_trash_folder_sync != NULL, NULL);
+
+               folder = class->get_trash_folder_sync (
+                       store, cancellable, error);
+               CAMEL_CHECK_GERROR (
+                       store, get_trash_folder_sync, folder != NULL, error);
+
+               return folder;
+       }
+
+       return camel_store_get_folder_sync (
+               store, CAMEL_VTRASH_NAME, 0, cancellable, error);
+}
+
+/**
+ * camel_store_get_trash_folder:
+ * @store: a #CamelStore
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously gets the folder in @store into which trash is delivered.
+ *
+ * When the operation is finished, @callback will be called.  You can
+ * then call camel_store_get_trash_folder_finish() to get the result of
+ * the operation.
  *
- * Returns: a #CamelFolderInfo tree, which must be freed with
- * #camel_store_free_folder_info, or %NULL.
+ * Since: 2.34
  **/
-CamelFolderInfo *
-camel_store_get_folder_info_sync (CamelStore *store,
-                                  const gchar *top,
-                                  guint32 flags,
-                                  GCancellable *cancellable,
-                                  GError **error)
+void
+camel_store_get_trash_folder (CamelStore *store,
+                              gint io_priority,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
+{
+       CamelStoreClass *class;
+
+       g_return_if_fail (CAMEL_IS_STORE (store));
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->get_trash_folder != NULL);
+
+       class->get_trash_folder (
+               store, io_priority, cancellable, callback, user_data);
+}
+
+/**
+ * camel_store_get_trash_folder_finish:
+ * @store: a #CamelStore
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_store_get_trash_folder().
+ *
+ * Returns: the trash folder for @store, or %NULL on error or if no such
+ * folder exists
+ *
+ * Since: 2.34
+ **/
+CamelFolder *
+camel_store_get_trash_folder_finish (CamelStore *store,
+                                     GAsyncResult *result,
+                                     GError **error)
 {
        CamelStoreClass *class;
-       CamelFolderInfo *info;
 
        g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
 
        class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->get_folder_info_sync != NULL, NULL);
+       g_return_val_if_fail (class->get_trash_folder_finish != NULL, NULL);
 
-       info = class->get_folder_info_sync (
-               store, top, flags, cancellable, error);
-       if (!(flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED))
-               CAMEL_CHECK_GERROR (
-                       store, get_folder_info_sync, info != NULL, error);
+       return class->get_trash_folder_finish (store, result, error);
+}
 
-       if (info && (top == NULL || *top == '\0') && (flags & CAMEL_STORE_FOLDER_INFO_NO_VIRTUAL) == 0) {
-               if (info->uri && (store->flags & CAMEL_STORE_VTRASH))
-                       /* the name of the Trash folder, used for deleted messages */
-                       add_special_info (store, info, CAMEL_VTRASH_NAME, _("Trash"), FALSE, CAMEL_FOLDER_VIRTUAL|CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_VTRASH|CAMEL_FOLDER_TYPE_TRASH);
-               if (info->uri && (store->flags & CAMEL_STORE_VJUNK))
-                       /* the name of the Junk folder, used for spam messages */
-                       add_special_info (store, info, CAMEL_VJUNK_NAME, _("Junk"), TRUE, CAMEL_FOLDER_VIRTUAL|CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_VTRASH|CAMEL_FOLDER_TYPE_JUNK);
+/**
+ * camel_store_create_folder_sync:
+ * @store: a #CamelStore
+ * @parent_name: name of the new folder's parent, or %NULL
+ * @folder_name: name of the folder to create
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Creates a new folder as a child of an existing folder.
+ * @parent_name can be %NULL to create a new top-level folder.
+ * The returned #CamelFolderInfo struct should be freed with
+ * camel_store_free_folder_info().
+ *
+ * Returns: info about the created folder, or %NULL on error
+ *
+ * Since: 2.34
+ **/
+CamelFolderInfo *
+camel_store_create_folder_sync (CamelStore *store,
+                                const gchar *parent_name,
+                                const gchar *folder_name,
+                                GCancellable *cancellable,
+                                GError **error)
+{
+       CamelStoreClass *class;
+       CamelFolderInfo *fi;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+       g_return_val_if_fail (folder_name != NULL, NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->create_folder_sync != NULL, NULL);
+
+       if ((parent_name == NULL || parent_name[0] == 0)
+           && (((store->flags & CAMEL_STORE_VTRASH) && strcmp (folder_name, CAMEL_VTRASH_NAME) == 0)
+               || ((store->flags & CAMEL_STORE_VJUNK) && strcmp (folder_name, CAMEL_VJUNK_NAME) == 0))) {
+               g_set_error (
+                       error, CAMEL_STORE_ERROR,
+                       CAMEL_STORE_ERROR_INVALID,
+                       _("Cannot create folder: %s: folder exists"),
+                       folder_name);
+               return NULL;
        }
 
-       if (camel_debug_start("store:folder_info")) {
-               gchar *url = camel_url_to_string (((CamelService *)store)->url, CAMEL_URL_HIDE_ALL);
-               printf("Get folder info(%p:%s, '%s') =\n", (gpointer) store, url, top?top:"<null>");
-               g_free (url);
-               dump_fi (info, 2);
-               camel_debug_end ();
+       camel_store_lock (store, CAMEL_STORE_FOLDER_LOCK);
+
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+               return NULL;
        }
 
-       return info;
+       fi = class->create_folder_sync (
+               store, parent_name, folder_name, cancellable, error);
+       CAMEL_CHECK_GERROR (store, create_folder_sync, fi != NULL, error);
+
+       camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+
+       return fi;
 }
 
 /**
- * camel_store_free_folder_info:
- * @store: a #CamelStore object
- * @fi: a #CamelFolderInfo as gotten via #camel_store_get_folder_info
+ * camel_store_create_folder:
+ * @store: a #CamelStore
+ * @parent_name: name of the new folder's parent, or %NULL
+ * @folder_name: name of the folder to create
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
  *
- * Frees the data returned by #camel_store_get_folder_info. If @fi is %NULL,
- * nothing is done, the routine simply returns.
+ * Asynchronously creates a new folder as a child of an existing folder.
+ * @parent_name can be %NULL to create a new top-level folder.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_store_create_folder_finish() to get the result of the operation.
+ *
+ * Since: 2.34
  **/
 void
-camel_store_free_folder_info (CamelStore *store,
-                              CamelFolderInfo *fi)
+camel_store_create_folder (CamelStore *store,
+                           const gchar *parent_name,
+                           const gchar *folder_name,
+                           gint io_priority,
+                           GCancellable *cancellable,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
 {
        CamelStoreClass *class;
 
        g_return_if_fail (CAMEL_IS_STORE (store));
-
-       if (fi == NULL)
-               return;
+       g_return_if_fail (folder_name != NULL);
 
        class = CAMEL_STORE_GET_CLASS (store);
-       g_return_if_fail (class->free_folder_info != NULL);
+       g_return_if_fail (class->create_folder != NULL);
 
-       class->free_folder_info (store, fi);
+       class->create_folder (
+               store, parent_name, folder_name, io_priority,
+               cancellable, callback, user_data);
 }
 
 /**
- * camel_store_free_folder_info_full:
- * @store: a #CamelStore object
- * @fi: a #CamelFolderInfo as gotten via #camel_store_get_folder_info
+ * camel_store_create_folder_finish:
+ * @store: a #CamelStore
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
  *
- * An implementation for #CamelStore::free_folder_info. Frees all
- * of the data.
+ * Finishes the operation started with camel_store_create_folder().
+ * The returned #CamelFolderInfo struct should be freed with
+ * camel_store_free_folder_info().
+ *
+ * Returns: info about the created folder, or %NULL on error
+ *
+ * Since: 2.34
  **/
-void
-camel_store_free_folder_info_full (CamelStore *store,
-                                   CamelFolderInfo *fi)
+CamelFolderInfo *
+camel_store_create_folder_finish (CamelStore *store,
+                                  GAsyncResult *result,
+                                  GError **error)
 {
-       camel_folder_info_free (fi);
+       CamelStoreClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->create_folder_finish != NULL, NULL);
+
+       return class->create_folder_finish (store, result, error);
 }
 
 /**
- * camel_store_free_folder_info_nop:
- * @store: a #CamelStore object
- * @fi: a #CamelFolderInfo as gotten via #camel_store_get_folder_info
+ * camel_store_delete_folder_sync:
+ * @store: a #CamelStore
+ * @folder_name: name of the folder to delete
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
  *
- * An implementation for #CamelStore::free_folder_info. Does nothing.
+ * Deletes the folder described by @folder_name.  The folder must be empty.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 2.34
  **/
-void
-camel_store_free_folder_info_nop (CamelStore *store,
-                                  CamelFolderInfo *fi)
+gboolean
+camel_store_delete_folder_sync (CamelStore *store,
+                                const gchar *folder_name,
+                                GCancellable *cancellable,
+                                GError **error)
 {
-       ;
+       CamelStoreClass *class;
+       gboolean success;
+       GError *local_error = NULL;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (folder_name != NULL, FALSE);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->delete_folder_sync != NULL, FALSE);
+
+       /* TODO: should probably be a parameter/bit on the storeinfo */
+       if (((store->flags & CAMEL_STORE_VTRASH) && strcmp (folder_name, CAMEL_VTRASH_NAME) == 0)
+           || ((store->flags & CAMEL_STORE_VJUNK) && strcmp (folder_name, CAMEL_VJUNK_NAME) == 0)) {
+               g_set_error (
+                       error, CAMEL_STORE_ERROR,
+                       CAMEL_STORE_ERROR_NO_FOLDER,
+                       _("Cannot delete folder: %s: Invalid operation"),
+                       folder_name);
+               return FALSE;
+       }
+
+       camel_store_lock (store, CAMEL_STORE_FOLDER_LOCK);
+
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+               return FALSE;
+       }
+
+       success = class->delete_folder_sync (
+               store, folder_name, cancellable, &local_error);
+       CAMEL_CHECK_GERROR (store, delete_folder_sync, success, &local_error);
+
+       /* ignore 'no such table' errors */
+       if (local_error != NULL &&
+           g_ascii_strncasecmp (local_error->message, "no such table", 13) == 0)
+               g_clear_error (&local_error);
+
+       if (local_error == NULL)
+               cs_delete_cached_folder(store, folder_name);
+       else
+               g_propagate_error (error, local_error);
+
+       camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+
+       return success;
 }
 
 /**
- * camel_folder_info_free:
- * @fi: a #CamelFolderInfo
+ * camel_store_delete_folder:
+ * @store: a #CamelStore
+ * @folder_name: name of the folder to delete
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
  *
- * Frees @fi.
+ * Asynchronously deletes the folder described by @folder_name.  The
+ * folder must be empty.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_store_delete_folder_finish() to get the result of the operation.
+ *
+ * Since: 2.34
  **/
 void
-camel_folder_info_free (CamelFolderInfo *fi)
+camel_store_delete_folder (CamelStore *store,
+                           const gchar *folder_name,
+                           gint io_priority,
+                           GCancellable *cancellable,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
 {
-       if (fi != NULL) {
-               camel_folder_info_free (fi->next);
-               camel_folder_info_free (fi->child);
-               g_free (fi->name);
-               g_free (fi->full_name);
-               g_free (fi->uri);
-               g_slice_free (CamelFolderInfo, fi);
-       }
+       CamelStoreClass *class;
+
+       g_return_if_fail (CAMEL_IS_STORE (store));
+       g_return_if_fail (folder_name != NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->delete_folder != NULL);
+
+       class->delete_folder (
+               store, folder_name, io_priority,
+               cancellable, callback, user_data);
 }
 
 /**
- * camel_folder_info_new:
+ * camel_store_delete_folder_finish:
+ * @store: a #CamelStore
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
  *
- * Returns: a new empty CamelFolderInfo instance
+ * Finishes the operation started with camel_store_delete_folder().
  *
- * Since: 2.22
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
-CamelFolderInfo *
-camel_folder_info_new (void)
+gboolean
+camel_store_delete_folder_finish (CamelStore *store,
+                                  GAsyncResult *result,
+                                  GError **error)
 {
-       return g_slice_new0 (CamelFolderInfo);
-}
+       CamelStoreClass *class;
 
-static gint
-folder_info_cmp (gconstpointer ap,
-                 gconstpointer bp)
-{
-       const CamelFolderInfo *a = ((CamelFolderInfo **)ap)[0];
-       const CamelFolderInfo *b = ((CamelFolderInfo **)bp)[0];
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->delete_folder_finish != NULL, FALSE);
 
-       return strcmp (a->full_name, b->full_name);
+       return class->delete_folder_finish (store, result, error);
 }
 
 /**
- * camel_folder_info_build:
- * @folders: an array of #CamelFolderInfo
- * @namespace: an ignorable prefix on the folder names
- * @separator: the hieararchy separator character
- * @short_names: %TRUE if the (short) name of a folder is the part after
- * the last @separator in the full name. %FALSE if it is the full name.
+ * camel_store_rename_folder_sync:
+ * @store: a #CamelStore
+ * @old_name: the current name of the folder
+ * @new_name: the new name of the folder
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
  *
- * This takes an array of folders and attaches them together according
- * to the hierarchy described by their full_names and @separator. If
- * @namespace is non-%NULL, then it will be ignored as a full_name
- * prefix, for purposes of comparison. If necessary,
- * #camel_folder_info_build will create additional #CamelFolderInfo with
- * %NULL urls to fill in gaps in the tree. The value of @short_names
- * is used in constructing the names of these intermediate folders.
+ * Renames the folder described by @old_name to @new_name.
  *
- * NOTE: This is deprected, do not use this.
- * FIXME: remove this/move it to imap, which is the only user of it now.
+ * Returns: %TRUE on success, %FALSE on error
  *
- * Returns: the top level of the tree of linked folder info.
+ * Since: 2.34
  **/
-CamelFolderInfo *
-camel_folder_info_build (GPtrArray *folders,
-                         const gchar *namespace,
-                         gchar separator,
-                         gboolean short_names)
+gboolean
+camel_store_rename_folder_sync (CamelStore *store,
+                                const gchar *old_namein,
+                                const gchar *new_name,
+                                GCancellable *cancellable,
+                                GError **error)
 {
-       CamelFolderInfo *fi, *pfi, *top = NULL, *tail = NULL;
-       GHashTable *hash;
-       gchar *p, *pname;
-       gint i, nlen;
+       CamelStoreClass *class;
+       CamelFolder *folder;
+       gint i, oldlen, namelen;
+       GPtrArray *folders = NULL;
+       gchar *old_name;
+       gboolean success;
 
-       if (!namespace)
-               namespace = "";
-       nlen = strlen (namespace);
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (old_namein != NULL, FALSE);
+       g_return_val_if_fail (new_name != NULL, FALSE);
 
-       qsort (folders->pdata, folders->len, sizeof (folders->pdata[0]), folder_info_cmp);
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->rename_folder_sync != NULL, FALSE);
 
-       /* Hash the folders. */
-       hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-       for (i = 0; i < folders->len; i++) {
-               fi = folders->pdata[i];
-               g_hash_table_insert (hash, g_strdup (fi->full_name), fi);
-       }
+       if (strcmp (old_namein, new_name) == 0)
+               return TRUE;
 
-       /* Now find parents. */
-       for (i = 0; i < folders->len; i++) {
-               fi = folders->pdata[i];
-               if (!strncmp (namespace, fi->full_name, nlen)
-                   && (p = strrchr (fi->full_name+nlen, separator))) {
-                       pname = g_strndup (fi->full_name, p - fi->full_name);
-                       pfi = g_hash_table_lookup (hash, pname);
-                       if (pfi) {
-                               g_free (pname);
-                       } else {
-                               /* we are missing a folder in the heirarchy so
-                                  create a fake folder node */
-                               const gchar *path;
-                               CamelURL *url;
-                               gchar *sep;
+       if (((store->flags & CAMEL_STORE_VTRASH) && strcmp (old_namein, CAMEL_VTRASH_NAME) == 0)
+           || ((store->flags & CAMEL_STORE_VJUNK) && strcmp (old_namein, CAMEL_VJUNK_NAME) == 0)) {
+               g_set_error (
+                       error, CAMEL_STORE_ERROR,
+                       CAMEL_STORE_ERROR_NO_FOLDER,
+                       _("Cannot rename folder: %s: Invalid operation"),
+                       old_namein);
+               return FALSE;
+       }
 
-                               pfi = camel_folder_info_new ();
-                               if (short_names) {
-                                       pfi->name = strrchr (pname, separator);
-                                       if (pfi->name)
-                                               pfi->name = g_strdup (pfi->name + 1);
-                                       else
-                                               pfi->name = g_strdup (pname);
-                               } else
-                                       pfi->name = g_strdup (pname);
+       /* need to save this, since old_namein might be folder->full_name, which could go away */
+       old_name = g_strdup (old_namein);
+       oldlen = strlen (old_name);
 
-                               url = camel_url_new (fi->uri, NULL);
-                               if (url->fragment)
-                                       path = url->fragment;
-                               else
-                                       path = url->path + 1;
+       camel_store_lock (store, CAMEL_STORE_FOLDER_LOCK);
 
-                               sep = strrchr (path, separator);
-                               if (sep)
-                                       *sep = '\0';
-                               else {
-                                       d(g_warning ("huh, no \"%c\" in \"%s\"?", separator, fi->uri));
-                               }
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+               return FALSE;
+       }
 
-                               pfi->full_name = g_strdup (path);
+       /* If the folder is open (or any subfolders of the open folder)
+          We need to rename them atomically with renaming the actual folder path */
+       if (store->folders) {
+               folders = camel_object_bag_list (store->folders);
+               for (i=0;i<folders->len;i++) {
+                       const gchar *full_name;
 
-                               /* since this is a "fake" folder node, it is not selectable */
-                               camel_url_set_param (url, "noselect", "yes");
-                               pfi->uri = camel_url_to_string (url, 0);
-                               camel_url_free (url);
+                       folder = folders->pdata[i];
+                       full_name = camel_folder_get_full_name (folder);
 
-                               g_hash_table_insert (hash, pname, pfi);
-                               g_ptr_array_add (folders, pfi);
+                       namelen = strlen (full_name);
+                       if ((namelen == oldlen &&
+                            strcmp (full_name, old_name) == 0)
+                           || ((namelen > oldlen)
+                               && strncmp (full_name, old_name, oldlen) == 0
+                               && full_name[oldlen] == '/')) {
+                               camel_folder_lock (folder, CAMEL_FOLDER_REC_LOCK);
+                       } else {
+                               g_ptr_array_remove_index_fast (folders, i);
+                               i--;
+                               g_object_unref (folder);
                        }
-                       tail = (CamelFolderInfo *)&pfi->child;
-                       while (tail->next)
-                               tail = tail->next;
-                       tail->next = fi;
-                       fi->parent = pfi;
-               } else if (!top)
-                       top = fi;
+               }
        }
-       g_hash_table_destroy (hash);
 
-       /* Link together the top-level folders */
-       tail = top;
-       for (i = 0; i < folders->len; i++) {
-               fi = folders->pdata[i];
+       /* Now try the real rename (will emit renamed signal) */
+       success = class->rename_folder_sync (
+               store, old_name, new_name, cancellable, error);
+       CAMEL_CHECK_GERROR (store, rename_folder_sync, success, error);
 
-               if (fi->child)
-                       fi->flags &= ~CAMEL_FOLDER_NOCHILDREN;
+       /* If it worked, update all open folders/unlock them */
+       if (folders) {
+               if (success) {
+                       guint32 flags = CAMEL_STORE_FOLDER_INFO_RECURSIVE;
+                       CamelFolderInfo *folder_info;
 
-               if (fi->parent || fi == top)
-                       continue;
-               if (tail == NULL) {
-                       tail = fi;
-                       top = fi;
-               } else {
-                       tail->next = fi;
-                       tail = fi;
-               }
-       }
+                       for (i=0;i<folders->len;i++) {
+                               const gchar *full_name;
+                               gchar *new;
 
-       return top;
-}
+                               folder = folders->pdata[i];
+                               full_name = camel_folder_get_full_name (folder);
 
-static CamelFolderInfo *
-folder_info_clone_rec (CamelFolderInfo *fi,
-                       CamelFolderInfo *parent)
-{
-       CamelFolderInfo *info;
+                               new = g_strdup_printf("%s%s", new_name, full_name + strlen(old_name));
+                               camel_object_bag_rekey (store->folders, folder, new);
+                               camel_folder_rename (folder, new);
+                               g_free (new);
 
-       info = camel_folder_info_new ();
-       info->parent = parent;
-       info->uri = g_strdup (fi->uri);
-       info->name = g_strdup (fi->name);
-       info->full_name = g_strdup (fi->full_name);
-       info->unread = fi->unread;
-       info->flags = fi->flags;
+                               camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+                               g_object_unref (folder);
+                       }
 
-       if (fi->next)
-               info->next = folder_info_clone_rec (fi->next, parent);
-       else
-               info->next = NULL;
+                       /* Emit renamed signal */
+                       if (store->flags & CAMEL_STORE_SUBSCRIPTIONS)
+                               flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
 
-       if (fi->child)
-               info->child = folder_info_clone_rec (fi->child, info);
-       else
-               info->child = NULL;
+                       folder_info = class->get_folder_info_sync (
+                               store, new_name, flags, cancellable, error);
+                       CAMEL_CHECK_GERROR (store, get_folder_info, folder_info != NULL, error);
 
-       return info;
-}
+                       if (folder_info != NULL) {
+                               camel_store_folder_renamed (store, old_name, folder_info);
+                               class->free_folder_info (store, folder_info);
+                       }
+               } else {
+                       /* Failed, just unlock our folders for re-use */
+                       for (i=0;i<folders->len;i++) {
+                               folder = folders->pdata[i];
+                               camel_folder_unlock (folder, CAMEL_FOLDER_REC_LOCK);
+                               g_object_unref (folder);
+                       }
+               }
+       }
 
-/**
- * camel_folder_info_clone:
- * @fi: a #CamelFolderInfo
- *
- * Clones @fi recursively.
- *
- * Returns: the cloned #CamelFolderInfo tree.
- **/
-CamelFolderInfo *
-camel_folder_info_clone (CamelFolderInfo *fi)
-{
-       if (fi == NULL)
-               return NULL;
+       camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
 
-       return folder_info_clone_rec (fi, NULL);
+       g_ptr_array_free (folders, TRUE);
+       g_free (old_name);
+
+       return success;
 }
 
 /**
- * camel_store_supports_subscriptions:
- * @store: a #CamelStore object
+ * camel_store_rename_folder:
+ * @store: a #CamelStore
+ * @old_name: the current name of the folder
+ * @new_name: the new name of the folder
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
  *
- * Get whether or not @store supports subscriptions to folders.
+ * Asynchronously renames the folder described by @old_name to @new_name.
  *
- * Returns: %TRUE if folder subscriptions are supported or %FALSE otherwise
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_store_rename_folder_finish() to get the result of the operation.
+ *
+ * Since: 2.34
  **/
-gboolean
-camel_store_supports_subscriptions (CamelStore *store)
+void
+camel_store_rename_folder (CamelStore *store,
+                           const gchar *old_name,
+                           const gchar *new_name,
+                           gint io_priority,
+                           GCancellable *cancellable,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
 {
-       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       CamelStoreClass *class;
 
-       return (store->flags & CAMEL_STORE_SUBSCRIPTIONS);
+       g_return_if_fail (CAMEL_IS_STORE (store));
+       g_return_if_fail (old_name != NULL);
+       g_return_if_fail (new_name != NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->rename_folder != NULL);
+
+       class->rename_folder (
+               store, old_name, new_name, io_priority,
+               cancellable, callback, user_data);
 }
 
 /**
- * camel_store_folder_is_subscribed:
- * @store: a #CamelStore object
- * @folder_name: full path of the folder
+ * camel_store_rename_folder_finish:
+ * @store: a #CamelStore
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
  *
- * Find out if a folder has been subscribed to.
+ * Finishes the operation started with camel_store_rename_folder().
  *
- * Returns: %TRUE if the folder has been subscribed to or %FALSE otherwise
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
 gboolean
-camel_store_folder_is_subscribed (CamelStore *store,
-                                  const gchar *folder_name)
+camel_store_rename_folder_finish (CamelStore *store,
+                                  GAsyncResult *result,
+                                  GError **error)
 {
        CamelStoreClass *class;
-       gboolean is_subscribed;
 
        g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
-       g_return_val_if_fail (folder_name != NULL, FALSE);
-       g_return_val_if_fail (store->flags & CAMEL_STORE_SUBSCRIPTIONS, FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
 
        class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->folder_is_subscribed != NULL, FALSE);
-
-       camel_store_lock (store, CAMEL_STORE_FOLDER_LOCK);
-
-       is_subscribed = class->folder_is_subscribed (store, folder_name);
+       g_return_val_if_fail (class->rename_folder_finish != NULL, FALSE);
 
-       camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
-
-       return is_subscribed;
+       return class->rename_folder_finish (store, result, error);
 }
 
 /**
  * camel_store_subscribe_folder_sync:
- * @store: a #CamelStore object
+ * @store: a #CamelStore
  * @folder_name: full path of the folder
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
- * Subscribe to the folder described by @folder_name.
+ * Subscribes to the folder described by @folder_name.
  *
- * Returns: %TRUE on success, %FALSE on failure
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
 gboolean
 camel_store_subscribe_folder_sync (CamelStore *store,
@@ -1526,6 +3054,12 @@ camel_store_subscribe_folder_sync (CamelStore *store,
 
        camel_store_lock (store, CAMEL_STORE_FOLDER_LOCK);
 
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+               return FALSE;
+       }
+
        success = class->subscribe_folder_sync (
                store, folder_name, cancellable, error);
        CAMEL_CHECK_GERROR (store, subscribe_folder_sync, success, error);
@@ -1536,15 +3070,83 @@ camel_store_subscribe_folder_sync (CamelStore *store,
 }
 
 /**
+ * camel_store_subscribe_folder:
+ * @store: a #CamelStore
+ * @folder_name: full path of the folder
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously subscribes to the folder described by @folder_name.
+ *
+ * When the operation is finished, @callback will be called.  You can
+ * then call camel_store_subscribe_folder_finish() to get the result of
+ * the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_store_subscribe_folder (CamelStore *store,
+                              const gchar *folder_name,
+                              gint io_priority,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
+{
+       CamelStoreClass *class;
+
+       g_return_if_fail (CAMEL_IS_STORE (store));
+       g_return_if_fail (folder_name != NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->subscribe_folder != NULL);
+
+       class->subscribe_folder (
+               store, folder_name, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_store_subscribe_folder_finish:
+ * @store: a #CamelStore
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_store_subscribe_folder().
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_store_subscribe_folder_finish (CamelStore *store,
+                                     GAsyncResult *result,
+                                     GError **error)
+{
+       CamelStoreClass *class;
+
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->subscribe_folder_finish != NULL, FALSE);
+
+       return class->subscribe_folder_finish (store, result, error);
+}
+
+/**
  * camel_store_unsubscribe_folder_sync:
- * @store: a #CamelStore object
+ * @store: a #CamelStore
  * @folder_name: full path of the folder
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
- * Unsubscribe from the folder described by @folder_name.
+ * Unsubscribes from the folder described by @folder_name.
  *
- * Returns: %TRUE on success, %FALSE on failure
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
 gboolean
 camel_store_unsubscribe_folder_sync (CamelStore *store,
@@ -1564,6 +3166,12 @@ camel_store_unsubscribe_folder_sync (CamelStore *store,
 
        camel_store_lock (store, CAMEL_STORE_FOLDER_LOCK);
 
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_store_unlock (store, CAMEL_STORE_FOLDER_LOCK);
+               return FALSE;
+       }
+
        success = class->unsubscribe_folder_sync (
                store, folder_name, cancellable, error);
        CAMEL_CHECK_GERROR (store, unsubscribe_folder_sync, success, error);
@@ -1577,171 +3185,257 @@ camel_store_unsubscribe_folder_sync (CamelStore *store,
 }
 
 /**
- * camel_store_noop_sync:
- * @store: a #CamelStore object
+ * camel_store_unsubscribe_folder:
+ * @store: a #CamelStore
+ * @folder_name: full path of the folder
+ * @io_priority: the I/O priority of the request
  * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously unsubscribes from the folder described by @folder_name.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_store_unsubscribe_folder_finish() to get the result of the
+ * operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_store_unsubscribe_folder (CamelStore *store,
+                                const gchar *folder_name,
+                                gint io_priority,
+                                GCancellable *cancellable,
+                                GAsyncReadyCallback callback,
+                                gpointer user_data)
+{
+       CamelStoreClass *class;
+
+       g_return_if_fail (CAMEL_IS_STORE (store));
+       g_return_if_fail (folder_name != NULL);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->unsubscribe_folder != NULL);
+
+       class->unsubscribe_folder (
+               store, folder_name, io_priority,
+               cancellable, callback, user_data);
+}
+
+/**
+ * camel_store_unsubscribe_folder_finish:
+ * @store: a #CamelStore
+ * @result: a #GAsyncResult
  * @error: return location for a #GError, or %NULL
  *
- * Pings @store so that its connection doesn't timeout.
+ * Finishes the operation started with camel_store_unsubscribe_folder().
  *
- * Returns: %TRUE on success, %FALSE on failure
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
 gboolean
-camel_store_noop_sync (CamelStore *store,
-                       GCancellable *cancellable,
-                       GError **error)
+camel_store_unsubscribe_folder_finish (CamelStore *store,
+                                       GAsyncResult *result,
+                                       GError **error)
 {
        CamelStoreClass *class;
-       gboolean success;
 
        g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
 
        class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->noop_sync != NULL, FALSE);
+       g_return_val_if_fail (class->unsubscribe_folder_finish != NULL, FALSE);
 
-       success = class->noop_sync (store, cancellable, error);
-       CAMEL_CHECK_GERROR (store, noop_sync, success, error);
-
-       return success;
+       return class->unsubscribe_folder_finish (store, result, error);
 }
 
 /**
- * camel_store_folder_uri_equal:
- * @store: a #CamelStore object
- * @uri0: a folder uri
- * @uri1: another folder uri
+ * camel_store_synchronize_sync:
+ * @store: a #CamelStore
+ * @expunge: whether to expunge after synchronizing
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
  *
- * Compares two folder uris to check that they are equal.
+ * Synchronizes any changes that have been made to @store and its folders
+ * with the real store.
  *
- * Returns: %TRUE if they are equal or %FALSE otherwise
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
-gint
-camel_store_folder_uri_equal (CamelStore *store,
-                              const gchar *uri0,
-                              const gchar *uri1)
+gboolean
+camel_store_synchronize_sync (CamelStore *store,
+                              gboolean expunge,
+                              GCancellable *cancellable,
+                              GError **error)
 {
        CamelStoreClass *class;
-       CamelProvider *provider;
-       CamelURL *url0, *url1;
-       gint equal;
+       gboolean success;
 
        g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
-       g_return_val_if_fail (uri0 && uri1, FALSE);
 
        class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->compare_folder_name != NULL, FALSE);
+       g_return_val_if_fail (class->synchronize_sync != NULL, FALSE);
 
-       provider = ((CamelService *) store)->provider;
+       success = class->synchronize_sync (store, expunge, cancellable, error);
+       CAMEL_CHECK_GERROR (store, synchronize_sync, success, error);
 
-       if (!(url0 = camel_url_new (uri0, NULL)))
-               return FALSE;
+       return success;
+}
 
-       if (!(url1 = camel_url_new (uri1, NULL))) {
-               camel_url_free (url0);
-               return FALSE;
-       }
+/**
+ * camel_store_synchronize:
+ * @store: a #CamelStore
+ * @expunge: whether to expunge after synchronizing
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Synchronizes any changes that have been made to @store and its folders
+ * with the real store asynchronously.
+ *
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_store_synchronize_finish() to get the result of the operation.
+ *
+ * Since: 2.34
+ **/
+void
+camel_store_synchronize (CamelStore *store,
+                         gboolean expunge,
+                         gint io_priority,
+                         GCancellable *cancellable,
+                         GAsyncReadyCallback callback,
+                         gpointer user_data)
+{
+       CamelStoreClass *class;
 
-       if ((equal = provider->url_equal (url0, url1))) {
-               const gchar *name0, *name1;
+       g_return_if_fail (CAMEL_IS_STORE (store));
 
-               if (provider->url_flags & CAMEL_URL_FRAGMENT_IS_PATH) {
-                       name0 = url0->fragment;
-                       name1 = url1->fragment;
-               } else {
-                       name0 = url0->path && url0->path[0] == '/' ? url0->path + 1 : url0->path;
-                       name1 = url1->path && url1->path[0] == '/' ? url1->path + 1 : url1->path;
-               }
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->synchronize != NULL);
 
-               if (name0 == NULL)
-                       g_warning("URI is badly formed, missing folder name: %s", uri0);
+       class->synchronize (
+               store, expunge, io_priority,
+               cancellable, callback, user_data);
+}
 
-               if (name1 == NULL)
-                       g_warning("URI is badly formed, missing folder name: %s", uri1);
+/**
+ * camel_store_synchronize_finish:
+ * @store: a #CamelStore
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_store_synchronize().
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
+ **/
+gboolean
+camel_store_synchronize_finish (CamelStore *store,
+                                GAsyncResult *result,
+                                GError **error)
+{
+       CamelStoreClass *class;
 
-               equal = name0 && name1 && class->compare_folder_name (name0, name1);
-       }
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
 
-       camel_url_free (url0);
-       camel_url_free (url1);
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->synchronize_finish != NULL, FALSE);
 
-       return equal;
+       return class->synchronize_finish (store, result, error);
 }
 
 /**
- * camel_store_can_refresh_folder
+ * camel_store_noop_sync:
  * @store: a #CamelStore
- * @info: a #CamelFolderInfo
+ * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
- * Returns if this folder (param info) should be checked for new mail or not.
- * It should not look into sub infos (info->child) or next infos, it should
- * return value only for the actual folder info.
- * Default behavior is that all Inbox folders are intended to be refreshed.
+ * Pings @store so its connection doesn't time out.
  *
- * Returns: whether folder should be checked for new mails
+ * Returns: %TRUE on success, %FALSE on error
  *
- * Since: 2.22
+ * Since: 2.34
  **/
 gboolean
-camel_store_can_refresh_folder (CamelStore *store,
-                                CamelFolderInfo *info,
-                                GError **error)
+camel_store_noop_sync (CamelStore *store,
+                       GCancellable *cancellable,
+                       GError **error)
 {
        CamelStoreClass *class;
+       gboolean success;
 
        g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
-       g_return_val_if_fail (info != NULL, FALSE);
 
        class = CAMEL_STORE_GET_CLASS (store);
-       g_return_val_if_fail (class->can_refresh_folder != NULL, FALSE);
+       g_return_val_if_fail (class->noop_sync != NULL, FALSE);
 
-       return class->can_refresh_folder (store, info, error);
+       success = class->noop_sync (store, cancellable, error);
+       CAMEL_CHECK_GERROR (store, noop_sync, success, error);
+
+       return success;
 }
 
 /**
- * camel_store_lock:
+ * camel_store_noop:
  * @store: a #CamelStore
- * @lock: lock type to lock
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
  *
- * Locks #store's #lock. Unlock it with camel_store_unlock().
+ * Pings @store asynchronously so its connection doesn't time out.
  *
- * Since: 2.32
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_store_noop_finish() to get the result of the operation.
+ *
+ * Since: 2.34
  **/
 void
-camel_store_lock (CamelStore *store,
-                  CamelStoreLock lock)
+camel_store_noop (CamelStore *store,
+                  gint io_priority,
+                  GCancellable *cancellable,
+                  GAsyncReadyCallback callback,
+                  gpointer user_data)
 {
+       CamelStoreClass *class;
+
        g_return_if_fail (CAMEL_IS_STORE (store));
 
-       switch (lock) {
-               case CAMEL_STORE_FOLDER_LOCK:
-                       g_static_rec_mutex_lock (&store->priv->folder_lock);
-                       break;
-               default:
-                       g_return_if_reached ();
-       }
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_if_fail (class->noop != NULL);
+
+       class->noop (store, io_priority, cancellable, callback, user_data);
 }
 
 /**
- * camel_store_unlock:
+ * camel_store_noop_finish:
  * @store: a #CamelStore
- * @lock: lock type to unlock
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
  *
- * Unlocks #store's #lock, previously locked with camel_store_lock().
+ * Finishes the operation started with camel_store_noop().
  *
- * Since: 2.32
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
-void
-camel_store_unlock (CamelStore *store,
-                    CamelStoreLock lock)
+gboolean
+camel_store_noop_finish (CamelStore *store,
+                         GAsyncResult *result,
+                         GError **error)
 {
-       g_return_if_fail (CAMEL_IS_STORE (store));
+       CamelStoreClass *class;
 
-       switch (lock) {
-               case CAMEL_STORE_FOLDER_LOCK:
-                       g_static_rec_mutex_unlock (&store->priv->folder_lock);
-                       break;
-               default:
-                       g_return_if_reached ();
-       }
+       g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_STORE_GET_CLASS (store);
+       g_return_val_if_fail (class->noop_finish != NULL, FALSE);
+
+       return class->noop_finish (store, result, error);
 }
index 641c6e1..ce53de6 100644 (file)
@@ -220,7 +220,7 @@ struct _CamelStoreClass {
        GHashFunc hash_folder_name;
        GCompareFunc compare_folder_name;
 
-       /* Methods */
+       /* Non-Blocking Methods */
        gboolean        (*can_refresh_folder)   (CamelStore *store,
                                                 CamelFolderInfo *info,
                                                 GError **error);
@@ -229,6 +229,7 @@ struct _CamelStoreClass {
        void            (*free_folder_info)     (CamelStore *store,
                                                 CamelFolderInfo *fi);
 
+       /* Synchronous I/O Methods */
        CamelFolder *   (*get_folder_sync)      (CamelStore *store,
                                                 const gchar *folder_name,
                                                 guint32 flags,
@@ -284,6 +285,124 @@ struct _CamelStoreClass {
                                                 GCancellable *cancellable,
                                                 GError **error);
 
+       /* Asyncrhonous I/O Methods (all have defaults) */
+       void            (*get_folder)           (CamelStore *store,
+                                                const gchar *folder_name,
+                                                guint32 flags,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       CamelFolder *   (*get_folder_finish)    (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*get_folder_info)      (CamelStore *store,
+                                                const gchar *top,
+                                                guint32 flags,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       CamelFolderInfo *
+                       (*get_folder_info_finish)
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*get_inbox_folder)     (CamelStore *store,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       CamelFolder *   (*get_inbox_folder_finish)
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*get_junk_folder)      (CamelStore *store,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       CamelFolder *   (*get_junk_folder_finish)
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*get_trash_folder)     (CamelStore *store,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       CamelFolder *   (*get_trash_folder_finish)
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*create_folder)        (CamelStore *store,
+                                                const gchar *parent_name,
+                                                const gchar *folder_name,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       CamelFolderInfo *
+                       (*create_folder_finish) (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*delete_folder)        (CamelStore *store,
+                                                const gchar *folder_name,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*delete_folder_finish) (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*rename_folder)        (CamelStore *store,
+                                                const gchar *old_name,
+                                                const gchar *new_name,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*rename_folder_finish) (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*subscribe_folder)     (CamelStore *store,
+                                                const gchar *folder_name,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*subscribe_folder_finish)
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*unsubscribe_folder)   (CamelStore *store,
+                                                const gchar *folder_name,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*unsubscribe_folder_finish)
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*synchronize)          (CamelStore *store,
+                                                gboolean expunge,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*synchronize_finish)   (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+       void            (*noop)                 (CamelStore *store,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*noop_finish)          (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+
        /* Signals */
        void            (*folder_created)       (CamelStore *store,
                                                 CamelFolderInfo *info);
@@ -352,6 +471,16 @@ CamelFolder *      camel_store_get_folder_sync     (CamelStore *store,
                                                 guint32 flags,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_store_get_folder          (CamelStore *store,
+                                                const gchar *folder_name,
+                                                guint32 flags,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+CamelFolder *  camel_store_get_folder_finish   (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
 CamelFolderInfo *
                camel_store_get_folder_info_sync
                                                (CamelStore *store,
@@ -359,50 +488,159 @@ CamelFolderInfo *
                                                 guint32 flags,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_store_get_folder_info     (CamelStore *store,
+                                                const gchar *top,
+                                                guint32 flags,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+CamelFolderInfo *
+               camel_store_get_folder_info_finish
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
 CamelFolder *  camel_store_get_inbox_folder_sync
                                                (CamelStore *store,
                                                 GCancellable *cancellable,
                                                 GError **error);
-CamelFolder *  camel_store_get_trash_folder_sync
-                                               (CamelStore *store,
+void           camel_store_get_inbox_folder    (CamelStore *store,
+                                                gint io_priority,
                                                 GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+CamelFolder *  camel_store_get_inbox_folder_finish
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
                                                 GError **error);
 CamelFolder *  camel_store_get_junk_folder_sync
                                                (CamelStore *store,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_store_get_junk_folder     (CamelStore *store,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+CamelFolder *  camel_store_get_junk_folder_finish
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
+CamelFolder *  camel_store_get_trash_folder_sync
+                                               (CamelStore *store,
+                                                GCancellable *cancellable,
+                                                GError **error);
+void           camel_store_get_trash_folder    (CamelStore *store,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+CamelFolder *  camel_store_get_trash_folder_finish
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
 CamelFolderInfo *
                camel_store_create_folder_sync  (CamelStore *store,
                                                 const gchar *parent_name,
                                                 const gchar *folder_name,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_store_create_folder       (CamelStore *store,
+                                                const gchar *parent_name,
+                                                const gchar *folder_name,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+CamelFolderInfo *
+               camel_store_create_folder_finish
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
 gboolean       camel_store_delete_folder_sync  (CamelStore *store,
                                                 const gchar *folder_name,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_store_delete_folder       (CamelStore *store,
+                                                const gchar *folder_name,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_store_delete_folder_finish
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
 gboolean       camel_store_rename_folder_sync  (CamelStore *store,
-                                                const gchar *old_namein,
+                                                const gchar *old_name,
                                                 const gchar *new_name,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_store_rename_folder       (CamelStore *store,
+                                                const gchar *old_name,
+                                                const gchar *new_name,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_store_rename_folder_finish
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
 gboolean       camel_store_subscribe_folder_sync
                                                (CamelStore *store,
                                                 const gchar *folder_name,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_store_subscribe_folder    (CamelStore *store,
+                                                const gchar *folder_name,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_store_subscribe_folder_finish
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
 gboolean       camel_store_unsubscribe_folder_sync
                                                (CamelStore *store,
                                                 const gchar *folder_name,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_store_unsubscribe_folder  (CamelStore *store,
+                                                const gchar *folder_name,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_store_unsubscribe_folder_finish
+                                               (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
 gboolean       camel_store_synchronize_sync    (CamelStore *store,
                                                 gboolean expunge,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_store_synchronize         (CamelStore *store,
+                                                gboolean expunge,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_store_synchronize_finish  (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
 gboolean       camel_store_noop_sync           (CamelStore *store,
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           camel_store_noop                (CamelStore *store,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_store_noop_finish         (CamelStore *store,
+                                                GAsyncResult *result,
+                                                GError **error);
 
 G_END_DECLS
 
index 24bdc7b..068c2ef 100644 (file)
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), CAMEL_TYPE_TRANSPORT, CamelTransportPrivate))
 
+typedef struct _AsyncContext AsyncContext;
+
 struct _CamelTransportPrivate {
        GMutex *send_lock;   /* for locking send operations */
 };
 
+struct _AsyncContext {
+       /* arguments */
+       CamelAddress *from;
+       CamelAddress *recipients;
+       CamelMimeMessage *message;
+};
+
 G_DEFINE_ABSTRACT_TYPE (CamelTransport, camel_transport, CAMEL_TYPE_SERVICE)
 
 static void
+async_context_free (AsyncContext *async_context)
+{
+       if (async_context->from != NULL)
+               g_object_unref (async_context->from);
+
+       if (async_context->recipients != NULL)
+               g_object_unref (async_context->recipients);
+
+       if (async_context->message != NULL)
+               g_object_unref (async_context->message);
+
+       g_slice_free (AsyncContext, async_context);
+}
+
+static void
 transport_finalize (GObject *object)
 {
        CamelTransportPrivate *priv;
@@ -56,6 +80,74 @@ transport_finalize (GObject *object)
 }
 
 static void
+transport_send_to_thread (GSimpleAsyncResult *simple,
+                          GObject *object,
+                          GCancellable *cancellable)
+{
+       AsyncContext *async_context;
+       GError *error = NULL;
+
+       async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+       camel_transport_send_to_sync (
+               CAMEL_TRANSPORT (object), async_context->message,
+               async_context->from, async_context->recipients,
+               cancellable, &error);
+
+       if (error != NULL) {
+               g_simple_async_result_set_from_error (simple, error);
+               g_error_free (error);
+       }
+}
+
+static void
+transport_send_to (CamelTransport *transport,
+                   CamelMimeMessage *message,
+                   CamelAddress *from,
+                   CamelAddress *recipients,
+                   gint io_priority,
+                   GCancellable *cancellable,
+                   GAsyncReadyCallback callback,
+                   gpointer user_data)
+{
+       GSimpleAsyncResult *simple;
+       AsyncContext *async_context;
+
+       async_context = g_slice_new0 (AsyncContext);
+       async_context->from = g_object_ref (from);
+       async_context->recipients = g_object_ref (recipients);
+       async_context->message = g_object_ref (message);
+
+       simple = g_simple_async_result_new (
+               G_OBJECT (transport), callback, user_data, transport_send_to);
+
+       g_simple_async_result_set_op_res_gpointer (
+               simple, async_context, (GDestroyNotify) async_context_free);
+
+       g_simple_async_result_run_in_thread (
+               simple, transport_send_to_thread, io_priority, cancellable);
+
+       g_object_unref (simple);
+}
+
+static gboolean
+transport_send_to_finish (CamelTransport *transport,
+                          GAsyncResult *result,
+                          GError **error)
+{
+       GSimpleAsyncResult *simple;
+
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (
+               result, G_OBJECT (transport), transport_send_to), FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+
+       /* Assume success unless a GError is set. */
+       return !g_simple_async_result_propagate_error (simple, error);
+}
+
+static void
 camel_transport_class_init (CamelTransportClass *class)
 {
        GObjectClass *object_class;
@@ -64,6 +156,9 @@ camel_transport_class_init (CamelTransportClass *class)
 
        object_class = G_OBJECT_CLASS (class);
        object_class->finalize = transport_finalize;
+
+       class->send_to = transport_send_to;
+       class->send_to_finish = transport_send_to_finish;
 }
 
 static void
@@ -75,8 +170,56 @@ camel_transport_init (CamelTransport *transport)
 }
 
 /**
+ * camel_transport_lock:
+ * @transport: a #CamelTransport
+ * @lock: lock type to lock
+ *
+ * Locks #transport's #lock. Unlock it with camel_transport_unlock().
+ *
+ * Since: 2.32
+ **/
+void
+camel_transport_lock (CamelTransport *transport,
+                      CamelTransportLock lock)
+{
+       g_return_if_fail (CAMEL_IS_TRANSPORT (transport));
+
+       switch (lock) {
+               case CAMEL_TRANSPORT_SEND_LOCK:
+                       g_mutex_lock (transport->priv->send_lock);
+                       break;
+               default:
+                       g_return_if_reached ();
+       }
+}
+
+/**
+ * camel_transport_unlock:
+ * @transport: a #CamelTransport
+ * @lock: lock type to unlock
+ *
+ * Unlocks #transport's #lock, previously locked with camel_transport_lock().
+ *
+ * Since: 2.32
+ **/
+void
+camel_transport_unlock (CamelTransport *transport,
+                        CamelTransportLock lock)
+{
+       g_return_if_fail (CAMEL_IS_TRANSPORT (transport));
+
+       switch (lock) {
+               case CAMEL_TRANSPORT_SEND_LOCK:
+                       g_mutex_unlock (transport->priv->send_lock);
+                       break;
+               default:
+                       g_return_if_reached ();
+       }
+}
+
+/**
  * camel_transport_send_to_sync:
- * @transport: a #CamelTransport object
+ * @transport: a #CamelTransport
  * @message: a #CamelMimeMessage to send
  * @from: a #CamelAddress to send from
  * @recipients: a #CamelAddress containing all recipients
@@ -84,10 +227,12 @@ camel_transport_init (CamelTransport *transport)
  * @error: return location for a #GError, or %NULL
  *
  * Sends the message to the given recipients, regardless of the contents
- * of @message. If the message contains a "Bcc" header, the transport
+ * of @message.  If the message contains a "Bcc" header, the transport
  * is responsible for stripping it.
  *
- * Return %TRUE on success or %FALSE on fail
+ * Returns: %TRUE on success or %FALSE on error
+ *
+ * Since: 2.34
  **/
 gboolean
 camel_transport_send_to_sync (CamelTransport *transport,
@@ -110,6 +255,12 @@ camel_transport_send_to_sync (CamelTransport *transport,
 
        camel_transport_lock (transport, CAMEL_TRANSPORT_SEND_LOCK);
 
+       /* Check for cancellation after locking. */
+       if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+               camel_transport_unlock (transport, CAMEL_TRANSPORT_SEND_LOCK);
+               return FALSE;
+       }
+
        success = class->send_to_sync (
                transport, message, from, recipients, cancellable, error);
        CAMEL_CHECK_GERROR (transport, send_to_sync, success, error);
@@ -120,49 +271,74 @@ camel_transport_send_to_sync (CamelTransport *transport,
 }
 
 /**
- * camel_transport_lock:
+ * camel_transport_send_to:
  * @transport: a #CamelTransport
- * @lock: lock type to lock
+ * @message: a #CamelMimeMessage to send
+ * @from: a #CamelAddress to send from
+ * @recipients: a #CamelAddress containing all recipients
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
  *
- * Locks #transport's #lock. Unlock it with camel_transport_unlock().
+ * Sends the message asynchronously to the given recipients, regardless of
+ * the contents of @message.  If the message contains a "Bcc" header, the
+ * transport is responsible for stripping it.
  *
- * Since: 2.32
+ * When the operation is finished, @callback will be called.  You can then
+ * call camel_transport_send_to_finish() to get the result of the operation.
+ *
+ * Since: 2.34
  **/
 void
-camel_transport_lock (CamelTransport *transport,
-                      CamelTransportLock lock)
+camel_transport_send_to (CamelTransport *transport,
+                         CamelMimeMessage *message,
+                         CamelAddress *from,
+                         CamelAddress *recipients,
+                         gint io_priority,
+                         GCancellable *cancellable,
+                         GAsyncReadyCallback callback,
+                         gpointer user_data)
 {
+       CamelTransportClass *class;
+
        g_return_if_fail (CAMEL_IS_TRANSPORT (transport));
+       g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
+       g_return_if_fail (CAMEL_IS_ADDRESS (from));
+       g_return_if_fail (CAMEL_IS_ADDRESS (recipients));
 
-       switch (lock) {
-               case CAMEL_TRANSPORT_SEND_LOCK:
-                       g_mutex_lock (transport->priv->send_lock);
-                       break;
-               default:
-                       g_return_if_reached ();
-       }
+       class = CAMEL_TRANSPORT_GET_CLASS (transport);
+       g_return_if_fail (class->send_to != NULL);
+
+       class->send_to (
+               transport, message, from, recipients, io_priority,
+               cancellable, callback, user_data);
 }
 
 /**
- * camel_transport_unlock:
+ * camel_transport_send_to_finish:
  * @transport: a #CamelTransport
- * @lock: lock type to unlock
+ * @result: a #GAsyncResult
+ * @error: return locaton for a #GError, or %NULL
  *
- * Unlocks #transport's #lock, previously locked with camel_transport_lock().
+ * Finishes the operation started with camel_transport_send_to().
  *
- * Since: 2.32
+ * Returns: %TRUE on success, %FALSE on error
+ *
+ * Since: 2.34
  **/
-void
-camel_transport_unlock (CamelTransport *transport,
-                        CamelTransportLock lock)
+gboolean
+camel_transport_send_to_finish (CamelTransport *transport,
+                                GAsyncResult *result,
+                                GError **error)
 {
-       g_return_if_fail (CAMEL_IS_TRANSPORT (transport));
+       CamelTransportClass *class;
 
-       switch (lock) {
-               case CAMEL_TRANSPORT_SEND_LOCK:
-                       g_mutex_unlock (transport->priv->send_lock);
-                       break;
-               default:
-                       g_return_if_reached ();
-       }
+       g_return_val_if_fail (CAMEL_IS_TRANSPORT (transport), FALSE);
+       g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+       class = CAMEL_TRANSPORT_GET_CLASS (transport);
+       g_return_val_if_fail (class->send_to_finish != NULL, FALSE);
+
+       return class->send_to_finish (transport, result, error);
 }
index 7a53961..ce01ef2 100644 (file)
@@ -76,26 +76,52 @@ struct _CamelTransport {
 struct _CamelTransportClass {
        CamelServiceClass parent_class;
 
+       /* Synchronous I/O Methods */
        gboolean        (*send_to_sync)         (CamelTransport *transport,
                                                 CamelMimeMessage *message,
                                                 CamelAddress *from,
                                                 CamelAddress *recipients,
                                                 GCancellable *cancellable,
                                                 GError **error);
-};
 
-GType          camel_transport_get_type        (void);
-gboolean       camel_transport_send_to_sync    (CamelTransport *transport,
+       /* Asynchronous I/O Methods (all have defaults) */
+       void            (*send_to)              (CamelTransport *transport,
                                                 CamelMimeMessage *message,
                                                 CamelAddress *from,
                                                 CamelAddress *recipients,
+                                                gint io_priority,
                                                 GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+       gboolean        (*send_to_finish)       (CamelTransport *transport,
+                                                GAsyncResult *result,
                                                 GError **error);
+};
+
+GType          camel_transport_get_type        (void);
 void           camel_transport_lock            (CamelTransport *transport,
                                                 CamelTransportLock lock);
 void           camel_transport_unlock          (CamelTransport *transport,
                                                 CamelTransportLock lock);
 
+gboolean       camel_transport_send_to_sync    (CamelTransport *transport,
+                                                CamelMimeMessage *message,
+                                                CamelAddress *from,
+                                                CamelAddress *recipients,
+                                                GCancellable *cancellable,
+                                                GError **error);
+void           camel_transport_send_to         (CamelTransport *transport,
+                                                CamelMimeMessage *message,
+                                                CamelAddress *from,
+                                                CamelAddress *recipients,
+                                                gint io_priority,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       camel_transport_send_to_finish  (CamelTransport *transport,
+                                                GAsyncResult *result,
+                                                GError **error);
+
 G_END_DECLS
 
 #endif /* CAMEL_TRANSPORT_H */
index 8585108..17c985c 100644 (file)
@@ -1210,7 +1210,7 @@ vee_folder_thaw (CamelFolder *folder)
 static gboolean
 vee_folder_append_message_sync (CamelFolder *folder,
                                 CamelMimeMessage *message,
-                                const CamelMessageInfo *info,
+                                CamelMessageInfo *info,
                                 gchar **appended_uid,
                                 GCancellable *cancellable,
                                 GError **error)
@@ -1372,8 +1372,8 @@ static gboolean
 vee_folder_transfer_messages_to_sync (CamelFolder *folder,
                                       GPtrArray *uids,
                                       CamelFolder *dest,
-                                      GPtrArray **transferred_uids,
                                       gboolean delete_originals,
+                                      GPtrArray **transferred_uids,
                                       GCancellable *cancellable,
                                       GError **error)
 {
index 63fd5db..31fd387 100644 (file)
@@ -70,7 +70,7 @@ transfer_messages (CamelFolder *folder,
 
        camel_folder_transfer_messages_to_sync (
                md->folder, md->uids, md->dest,
-               NULL, md->delete, md->cancellable, error);
+               md->delete, NULL, md->cancellable, error);
 
        if (md->cancellable != NULL)
                g_object_unref (md->cancellable);
@@ -86,7 +86,7 @@ transfer_messages (CamelFolder *folder,
 static gboolean
 vtrash_folder_append_message_sync (CamelFolder *folder,
                                    CamelMimeMessage *message,
-                                   const CamelMessageInfo *info,
+                                   CamelMessageInfo *info,
                                    gchar **appended_uid,
                                    GCancellable *cancellable,
                                    GError **error)
@@ -102,8 +102,8 @@ static gboolean
 vtrash_folder_transfer_messages_to_sync (CamelFolder *source,
                                          GPtrArray *uids,
                                          CamelFolder *dest,
-                                         GPtrArray **transferred_uids,
                                          gboolean delete_originals,
+                                         GPtrArray **transferred_uids,
                                          GCancellable *cancellable,
                                          GError **error)
 {
index 53da6ce..622c57b 100644 (file)
@@ -77,7 +77,7 @@ struct _CamelGroupwiseFolderPrivate {
 extern gint camel_application_is_exiting;
 
 /*prototypes*/
-static gboolean groupwise_transfer_messages_to_sync (CamelFolder *source, GPtrArray *uids, CamelFolder *destination, GPtrArray **transferred_uids, gboolean delete_originals, GCancellable *cancellable, GError **error);
+static gboolean groupwise_transfer_messages_to_sync (CamelFolder *source, GPtrArray *uids, CamelFolder *destination, gboolean delete_originals, GPtrArray **transferred_uids, GCancellable *cancellable, GError **error);
 void convert_to_calendar (EGwItem *item, gchar **str, gint *len);
 static void convert_to_task (EGwItem *item, gchar **str, gint *len);
 static void convert_to_note (EGwItem *item, gchar **str, gint *len);
@@ -548,7 +548,7 @@ move_to_mailbox (CamelFolder *folder,
                CAMEL_GW_MESSAGE_JUNK, 0);
        if (dest)
                groupwise_transfer_messages_to_sync (
-                       folder, uids, dest, NULL, TRUE, cancellable, error);
+                       folder, uids, dest, TRUE, NULL, cancellable, error);
        else
                g_warning ("No Mailbox folder found");
 
@@ -577,7 +577,7 @@ move_to_junk (CamelFolder *folder,
 
        if (dest)
                groupwise_transfer_messages_to_sync (
-                       folder, uids, dest, NULL, TRUE, cancellable, error);
+                       folder, uids, dest, TRUE, NULL, cancellable, error);
        else {
                fi = create_junk_folder (parent_store);
                dest = camel_store_get_folder_sync (
@@ -586,7 +586,7 @@ move_to_junk (CamelFolder *folder,
                        g_warning ("Could not get JunkFolder:Message not moved");
                else
                        groupwise_transfer_messages_to_sync (
-                               folder, uids, dest, NULL, TRUE, cancellable, error);
+                               folder, uids, dest, TRUE, NULL, cancellable, error);
        }
        update_junk_list (parent_store, info, ADD_JUNK_ENTRY);
 }
@@ -1030,7 +1030,7 @@ update_update (CamelSession *session,
                goto end1;
        }
 
-       camel_operation_start (
+       camel_operation_push_message (
                msg->cancellable,
                _("Checking for deleted messages %s"),
                camel_folder_get_name (m->folder));
@@ -1103,12 +1103,12 @@ update_update (CamelSession *session,
 
        g_print ("\nNumber of items in the folder: %d \n", g_list_length(items_full_list));
        gw_update_all_items (m->folder, items_full_list, NULL, NULL);
-       camel_operation_end (msg->cancellable);
+       camel_operation_pop_message (msg->cancellable);
 
        return;
  end1:
        camel_service_unlock (CAMEL_SERVICE (gw_store), CAMEL_SERVICE_REC_CONNECT_LOCK);
-       camel_operation_end (msg->cancellable);
+       camel_operation_pop_message (msg->cancellable);
        if (items_full_list) {
                g_list_foreach (items_full_list, (GFunc)g_free, NULL);
                g_list_free (items_full_list);
@@ -1515,7 +1515,7 @@ gw_update_cache (CamelFolder *folder,
                is_junk = TRUE;
        }
 
-       camel_operation_start (
+       camel_operation_push_message (
                cancellable,
                _("Fetching summary information for new messages in %s"),
                camel_folder_get_name (folder));
@@ -1714,7 +1714,7 @@ gw_update_cache (CamelFolder *folder,
                g_object_unref (item);
        }
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        g_free (container_id);
        g_string_free (str_to, TRUE);
@@ -2060,7 +2060,7 @@ groupwise_folder_item_to_msg ( CamelFolder *folder,
        msg = camel_mime_message_new ();
        if (has_mime_822 && body) {
                temp_stream = camel_stream_mem_new_with_buffer (body, body_len);
-               if (camel_data_wrapper_construct_from_stream_sync ((CamelDataWrapper *) msg, temp_stream, NULL, error) == -1) {
+               if (!camel_data_wrapper_construct_from_stream_sync ((CamelDataWrapper *) msg, temp_stream, NULL, error)) {
                        g_object_unref (msg);
                        g_object_unref (temp_stream);
                        msg = NULL;
@@ -2398,7 +2398,7 @@ groupwise_folder_constructed (GObject *object)
 static gboolean
 groupwise_append_message_sync (CamelFolder *folder,
                                CamelMimeMessage *message,
-                               const CamelMessageInfo *info,
+                               CamelMessageInfo *info,
                                gchar **appended_uid,
                                GCancellable *cancellable,
                                GError **error)
@@ -2653,7 +2653,7 @@ groupwise_folder_get_message_sync (CamelFolder *folder,
                camel_stream_reset (stream, NULL);
                camel_stream_write_to_stream (cache_stream, stream, cancellable, NULL);
                camel_stream_reset (stream, NULL);
-               if (camel_data_wrapper_construct_from_stream_sync ((CamelDataWrapper *) msg, stream, cancellable, error) == -1) {
+               if (!camel_data_wrapper_construct_from_stream_sync ((CamelDataWrapper *) msg, stream, cancellable, error)) {
                        if (errno == EINTR) {
                                g_object_unref (msg);
                                g_object_unref (cache_stream);
@@ -2810,8 +2810,8 @@ static gboolean
 groupwise_transfer_messages_to_sync (CamelFolder *source,
                                      GPtrArray *uids,
                                      CamelFolder *destination,
-                                     GPtrArray **transferred_uids,
                                      gboolean delete_originals,
+                                     GPtrArray **transferred_uids,
                                      GCancellable *cancellable,
                                      GError **error)
 {
index 0927106..81fa47c 100644 (file)
@@ -175,7 +175,7 @@ groupwise_entry_play_append (CamelOfflineJournal *journal,
        }
 
        message = camel_mime_message_new ();
-       if (camel_data_wrapper_construct_from_stream_sync ((CamelDataWrapper *) message, stream, cancellable, error) == -1) {
+       if (!camel_data_wrapper_construct_from_stream_sync ((CamelDataWrapper *) message, stream, cancellable, error)) {
                g_object_unref (message);
                g_object_unref (stream);
                goto done;
@@ -229,7 +229,7 @@ groupwise_entry_play_transfer (CamelOfflineJournal *journal,
                g_ptr_array_add (uids, entry->original_uid);
 
                if (camel_folder_transfer_messages_to_sync (
-                       src, uids, folder, &xuids, FALSE, cancellable, error)) {
+                       src, uids, folder, FALSE, &xuids, cancellable, error)) {
                        real = (CamelGroupwiseMessageInfo *) camel_folder_summary_uid (folder->summary, xuids->pdata[0]);
 
                        /* transfer all the system flags, user flags/tags, etc */
index cdc8cd9..0a8d5ff 100644 (file)
@@ -667,7 +667,7 @@ groupwise_store_get_folder_sync (CamelStore *store,
                        return NULL;
                }
 
-               camel_operation_start (
+               camel_operation_push_message (
                        cancellable,
                        _("Fetching summary information for new messages in %s"),
                        camel_folder_get_name (folder));
@@ -712,7 +712,7 @@ groupwise_store_get_folder_sync (CamelStore *store,
 
                e_gw_connection_destroy_cursor (priv->cnc, container_id, cursor);
 
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
        }
        if (done && all_ok) {
                if (summary->time_string)
@@ -798,7 +798,7 @@ gw_store_reload_folder (CamelGroupwiseStore *gw_store,
                                        return FALSE;
                        }
 
-                       camel_operation_start (
+                       camel_operation_push_message (
                                cancellable,
                                _("Fetching summary information for new messages in %s"),
                                camel_folder_get_name (folder));
@@ -815,7 +815,7 @@ gw_store_reload_folder (CamelGroupwiseStore *gw_store,
                                                                error, CAMEL_SERVICE_ERROR,
                                                                CAMEL_SERVICE_ERROR_INVALID,
                                                                _("Authentication failed"));
-                                                       camel_operation_end (cancellable);
+                                                       camel_operation_pop_message (cancellable);
                                                        g_free (container_id);
                                                        return FALSE;
                                        }
@@ -849,7 +849,7 @@ gw_store_reload_folder (CamelGroupwiseStore *gw_store,
 
                        e_gw_connection_destroy_cursor (priv->cnc, container_id, cursor);
 
-                       camel_operation_end (cancellable);
+                       camel_operation_pop_message (cancellable);
        }
 
        if (done) {
index 12caf78..3b5336b 100644 (file)
@@ -94,7 +94,7 @@ groupwise_send_to_sync (CamelTransport *transport,
                                    CAMEL_URL_HIDE_PARAMS   |
                                    CAMEL_URL_HIDE_AUTH) );
 
-       camel_operation_start (cancellable, _("Sending Message") );
+       camel_operation_push_message (cancellable, _("Sending Message") );
 
        /*camel groupwise store and cnc*/
        store = camel_session_get_store (service->session, url, NULL);
@@ -113,7 +113,7 @@ groupwise_send_to_sync (CamelTransport *transport,
        cnc = cnc_lookup (priv);
        if (!cnc) {
                g_warning ("||| Eh!!! Failure |||\n");
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                g_set_error (
                        error, CAMEL_SERVICE_ERROR,
                        CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
@@ -140,7 +140,7 @@ groupwise_send_to_sync (CamelTransport *transport,
        status = e_gw_connection_send_item (cnc, item, &sent_item_list);
        if (status != E_GW_CONNECTION_STATUS_OK) {
                g_warning (" Error Sending mail");
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                e_gw_item_set_link_info (item, NULL);
                g_object_unref (item);
                if (temp_item)
@@ -169,7 +169,7 @@ groupwise_send_to_sync (CamelTransport *transport,
                g_object_unref (temp_item);
        g_object_unref (item);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return TRUE;
 }
index 0f073a3..6517e80 100644 (file)
@@ -89,23 +89,27 @@ static CamelMimeMessage *imap_get_message_sync (CamelFolder *folder, const gchar
 static gboolean imap_synchronize_message_sync (CamelFolder *folder, const gchar *uid, GCancellable *cancellable,
                               GError **error);
 static gboolean imap_append_online (CamelFolder *folder, CamelMimeMessage *message,
-                               const CamelMessageInfo *info, gchar **appended_uid,
+                               CamelMessageInfo *info, gchar **appended_uid,
                                GCancellable *cancellable,
                                GError **error);
 static gboolean imap_append_offline (CamelFolder *folder, CamelMimeMessage *message,
-                                const CamelMessageInfo *info, gchar **appended_uid,
+                                CamelMessageInfo *info, gchar **appended_uid,
                                 GError **error);
 
-static gboolean imap_transfer_online (CamelFolder *source, GPtrArray *uids,
-                                 CamelFolder *dest, GPtrArray **transferred_uids,
-                                 gboolean delete_originals,
-                                 GCancellable *cancellable,
-                                 GError **error);
-static gboolean imap_transfer_offline (CamelFolder *source, GPtrArray *uids,
-                                  CamelFolder *dest, GPtrArray **transferred_uids,
-                                  gboolean delete_originals,
-                                  GCancellable *cancellable,
-                                  GError **error);
+static gboolean        imap_transfer_online            (CamelFolder *source,
+                                                GPtrArray *uids,
+                                                CamelFolder *dest,
+                                                gboolean delete_originals,
+                                                GPtrArray **transferred_uids,
+                                                GCancellable *cancellable,
+                                                GError **error);
+static gboolean        imap_transfer_offline           (CamelFolder *source,
+                                                GPtrArray *uids,
+                                                CamelFolder *dest,
+                                                gboolean delete_originals,
+                                                GPtrArray **transferred_uids,
+                                                GCancellable *cancellable,
+                                                GError **error);
 
 /* searching */
 static GPtrArray *imap_search_by_expression (CamelFolder *folder, const gchar *expression, GError **error);
@@ -124,11 +128,14 @@ static CamelImapMessageInfo * imap_folder_summary_uid_or_error (
        const gchar * uid,
        GError **error);
 
-static gboolean
-imap_transfer_messages (CamelFolder *source, GPtrArray *uids,
-                       CamelFolder *dest, GPtrArray **transferred_uids,
-                       gboolean delete_originals, gboolean can_call_sync,
-                       GCancellable *cancellable, GError **error);
+static gboolean        imap_transfer_messages          (CamelFolder *source,
+                                                GPtrArray *uids,
+                                                CamelFolder *dest,
+                                                gboolean delete_originals,
+                                                GPtrArray **transferred_uids,
+                                                gboolean can_call_sync,
+                                                GCancellable *cancellable,
+                                                GError **error);
 
 #ifdef G_OS_WIN32
 /* The strtok() in Microsoft's C library is MT-safe (but still uses
@@ -979,13 +986,13 @@ imap_rescan (CamelFolder *folder,
        }
 
        /* Check UIDs and flags of all messages we already know of. */
-       camel_operation_start (
+       camel_operation_push_message (
                cancellable, _("Scanning for changed messages in %s"),
                camel_folder_get_name (folder));
        uid = camel_folder_summary_uid_from_index (folder->summary, summary_len - 1);
 
        if (!uid) {
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                return TRUE;
        }
 
@@ -994,7 +1001,7 @@ imap_rescan (CamelFolder *folder,
                "UID FETCH 1:%s (FLAGS)", uid);
        g_free (uid);
        if (!ok) {
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                return FALSE;
        }
 
@@ -1029,13 +1036,13 @@ imap_rescan (CamelFolder *folder,
        }
 
        if (summary_got == 0 && summary_len == 0) {
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
                g_free (new);
                return TRUE;
        }
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        if (type == CAMEL_IMAP_RESPONSE_ERROR || camel_application_is_exiting) {
                for (i = 0; i < summary_len && new[i].uid; i++) {
@@ -1486,8 +1493,8 @@ move_messages (CamelFolder *src_folder,
        if (src_folder != des_folder) {
                /* do 'copy' to not be bothered with CAMEL_MESSAGE_DELETED again */
                if (!imap_transfer_messages (
-                       src_folder, uids, des_folder, NULL,
-                       FALSE, FALSE, cancellable, error))
+                       src_folder, uids, des_folder, FALSE,
+                       NULL, FALSE, cancellable, error))
                        return;
        }
 
@@ -2175,7 +2182,7 @@ get_temp_uid (void)
 static gboolean
 imap_append_offline (CamelFolder *folder,
                      CamelMimeMessage *message,
-                     const CamelMessageInfo *info,
+                     CamelMessageInfo *info,
                      gchar **appended_uid,
                      GError **error)
 {
@@ -2231,7 +2238,7 @@ imap_folder_uid_in_ignore_recent (CamelImapFolder *imap_folder, const gchar *uid
 static CamelImapResponse *
 do_append (CamelFolder *folder,
            CamelMimeMessage *message,
-           const CamelMessageInfo *info,
+           CamelMessageInfo *info,
            gchar **uid,
            GCancellable *cancellable,
            GError **error)
@@ -2341,7 +2348,7 @@ retry:
 static gboolean
 imap_append_online (CamelFolder *folder,
                     CamelMimeMessage *message,
-                    const CamelMessageInfo *info,
+                    CamelMessageInfo *info,
                     gchar **appended_uid,
                     GCancellable *cancellable,
                     GError **error)
@@ -2397,7 +2404,7 @@ imap_append_online (CamelFolder *folder,
 gboolean
 camel_imap_append_resyncing (CamelFolder *folder,
                              CamelMimeMessage *message,
-                             const CamelMessageInfo *info,
+                             CamelMessageInfo *info,
                              gchar **appended_uid,
                              GCancellable *cancellable,
                              GError **error)
@@ -2439,8 +2446,8 @@ static gboolean
 imap_transfer_offline (CamelFolder *source,
                        GPtrArray *uids,
                        CamelFolder *dest,
-                       GPtrArray **transferred_uids,
                        gboolean delete_originals,
+                       GPtrArray **transferred_uids,
                        GCancellable *cancellable,
                        GError **error)
 {
@@ -2758,8 +2765,8 @@ static gboolean
 imap_transfer_messages (CamelFolder *source,
                         GPtrArray *uids,
                         CamelFolder *dest,
-                        GPtrArray **transferred_uids,
                         gboolean delete_originals,
+                        GPtrArray **transferred_uids,
                         gboolean can_call_sync,
                         GCancellable *cancellable,
                         GError **error)
@@ -2774,8 +2781,8 @@ imap_transfer_messages (CamelFolder *source,
 
        if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store)))
                return imap_transfer_offline (
-                       source, uids, dest, transferred_uids,
-                       delete_originals, cancellable, error);
+                       source, uids, dest, delete_originals,
+                       transferred_uids, cancellable, error);
 
        /* Sync message flags if needed. */
        if (can_call_sync && !imap_synchronize_sync (
@@ -2806,22 +2813,22 @@ static gboolean
 imap_transfer_online (CamelFolder *source,
                       GPtrArray *uids,
                       CamelFolder *dest,
-                      GPtrArray **transferred_uids,
                       gboolean delete_originals,
+                      GPtrArray **transferred_uids,
                       GCancellable *cancellable,
                       GError **error)
 {
        return imap_transfer_messages (
-               source, uids, dest, transferred_uids,
-               delete_originals, TRUE, cancellable, error);
+               source, uids, dest, delete_originals,
+               transferred_uids, TRUE, cancellable, error);
 }
 
 gboolean
 camel_imap_transfer_resyncing (CamelFolder *source,
                                GPtrArray *uids,
                                CamelFolder *dest,
-                               GPtrArray **transferred_uids,
                                gboolean delete_originals,
+                               GPtrArray **transferred_uids,
                                GCancellable *cancellable,
                                GError **error)
 {
@@ -3097,7 +3104,7 @@ get_content (CamelImapFolder *imap_folder,
        if (camel_content_type_is (ci->type, "multipart", "signed")) {
                CamelMultipartSigned *body_mp;
                gchar *spec;
-               gint ret;
+               gboolean success;
 
                /* Note: because we get the content parts uninterpreted anyway, we could potentially
                   just use the normalmultipart code, except that multipart/signed wont let you yet! */
@@ -3116,10 +3123,10 @@ get_content (CamelImapFolder *imap_folder,
 
                stream = camel_imap_folder_fetch_data (imap_folder, uid, spec, FALSE, cancellable, error);
                if (stream) {
-                       ret = camel_data_wrapper_construct_from_stream_sync (
+                       success = camel_data_wrapper_construct_from_stream_sync (
                                CAMEL_DATA_WRAPPER (body_mp), stream, cancellable, error);
                        g_object_unref (CAMEL_OBJECT (stream));
-                       if (ret == -1) {
+                       if (!success) {
                                g_object_unref ( body_mp);
                                return NULL;
                        }
@@ -3154,13 +3161,13 @@ get_content (CamelImapFolder *imap_folder,
                        sprintf (child_spec + speclen, "%d.MIME", num++);
                        stream = camel_imap_folder_fetch_data (imap_folder, uid, child_spec, FALSE, cancellable, error);
                        if (stream) {
-                               gint ret;
+                               gboolean success;
 
                                part = camel_mime_part_new ();
-                               ret = camel_data_wrapper_construct_from_stream_sync (
+                               success = camel_data_wrapper_construct_from_stream_sync (
                                        CAMEL_DATA_WRAPPER (part), stream, cancellable, error);
                                g_object_unref (CAMEL_OBJECT (stream));
-                               if (ret == -1) {
+                               if (!success) {
                                        g_object_unref (CAMEL_OBJECT (part));
                                        g_object_unref (CAMEL_OBJECT (body_mp));
                                        g_free (child_spec);
@@ -3244,7 +3251,7 @@ get_message (CamelImapFolder *imap_folder,
        CamelMimeMessage *msg;
        CamelStream *stream;
        gchar *section_text, *part_spec;
-       gint ret;
+       gboolean success;
 
        folder = CAMEL_FOLDER (imap_folder);
        parent_store = camel_folder_get_parent_store (folder);
@@ -3262,10 +3269,10 @@ get_message (CamelImapFolder *imap_folder,
                return NULL;
 
        msg = camel_mime_message_new ();
-       ret = camel_data_wrapper_construct_from_stream_sync (
+       success = camel_data_wrapper_construct_from_stream_sync (
                CAMEL_DATA_WRAPPER (msg), stream, cancellable, error);
        g_object_unref (CAMEL_OBJECT (stream));
-       if (ret == -1) {
+       if (!success) {
                g_object_unref (CAMEL_OBJECT (msg));
                return NULL;
        }
@@ -3302,7 +3309,7 @@ get_message_simple (CamelImapFolder *imap_folder,
                     GError **error)
 {
        CamelMimeMessage *msg;
-       gint ret;
+       gboolean success;
 
        if (!stream) {
                stream = camel_imap_folder_fetch_data (imap_folder, uid, "",
@@ -3312,10 +3319,10 @@ get_message_simple (CamelImapFolder *imap_folder,
        }
 
        msg = camel_mime_message_new ();
-       ret = camel_data_wrapper_construct_from_stream_sync (
+       success = camel_data_wrapper_construct_from_stream_sync (
                CAMEL_DATA_WRAPPER (msg), stream, cancellable, error);
        g_object_unref (CAMEL_OBJECT (stream));
-       if (ret == -1) {
+       if (!success) {
                g_prefix_error (error, _("Unable to retrieve message: "));
                g_object_unref (CAMEL_OBJECT (msg));
                return NULL;
@@ -3730,8 +3737,8 @@ add_message_from_data (CamelFolder *folder,
                g_ptr_array_set_size (messages, seq - first + 1);
 
        msg = camel_mime_message_new ();
-       if (camel_data_wrapper_construct_from_stream_sync (
-               CAMEL_DATA_WRAPPER (msg), stream, cancellable, NULL) == -1) {
+       if (!camel_data_wrapper_construct_from_stream_sync (
+               CAMEL_DATA_WRAPPER (msg), stream, cancellable, NULL)) {
                g_object_unref (CAMEL_OBJECT (msg));
                return;
        }
@@ -3907,7 +3914,7 @@ imap_update_summary (CamelFolder *folder,
                return FALSE;
        }
 
-       camel_operation_start (
+       camel_operation_push_message (
                cancellable,
                _("Fetching summary information for new messages in %s"),
                camel_folder_get_name (folder));
@@ -3954,7 +3961,7 @@ imap_update_summary (CamelFolder *folder,
                g_ptr_array_add (fetch_data, data);
        }
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        if (type == CAMEL_IMAP_RESPONSE_ERROR || camel_application_is_exiting) {
                if (type != CAMEL_IMAP_RESPONSE_ERROR && type != CAMEL_IMAP_RESPONSE_TAGGED)
@@ -3989,7 +3996,7 @@ imap_update_summary (CamelFolder *folder,
                qsort (needheaders->pdata, needheaders->len,
                       sizeof (gpointer), uid_compar);
 
-               camel_operation_start (
+               camel_operation_push_message (
                        cancellable,
                        _("Fetching summary information for new messages in %s"),
                        camel_folder_get_name (folder));
@@ -4000,7 +4007,7 @@ imap_update_summary (CamelFolder *folder,
                                                       "UID FETCH %s BODYSTRUCTURE BODY.PEEK[%s]",
                                                       uidset, header_spec->str)) {
                                g_ptr_array_free (needheaders, TRUE);
-                               camel_operation_end (cancellable);
+                               camel_operation_pop_message (cancellable);
                                g_free (uidset);
                                g_string_free (header_spec, TRUE);
                                goto lose;
@@ -4028,7 +4035,7 @@ imap_update_summary (CamelFolder *folder,
 
                        if (type == CAMEL_IMAP_RESPONSE_ERROR || camel_application_is_exiting) {
                                g_ptr_array_free (needheaders, TRUE);
-                               camel_operation_end (cancellable);
+                               camel_operation_pop_message (cancellable);
 
                                if (type != CAMEL_IMAP_RESPONSE_ERROR && type != CAMEL_IMAP_RESPONSE_TAGGED)
                                        camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
@@ -4038,7 +4045,7 @@ imap_update_summary (CamelFolder *folder,
                }
                g_string_free (header_spec, TRUE);
                g_ptr_array_free (needheaders, TRUE);
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
        }
 
        /* Now finish up summary entries (fix UIDs, set flags and size) */
index e24bd96..7ea9711 100644 (file)
@@ -102,15 +102,15 @@ CamelStream *     camel_imap_folder_fetch_data    (CamelImapFolder *imap_folder,
                                                 GError **error);
 gboolean       camel_imap_append_resyncing     (CamelFolder *folder,
                                                 CamelMimeMessage *message,
-                                                const CamelMessageInfo *info,
+                                                CamelMessageInfo *info,
                                                 gchar **appended_uid,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       camel_imap_transfer_resyncing   (CamelFolder *source,
                                                 GPtrArray *uids,
                                                 CamelFolder *dest,
-                                                GPtrArray **transferred_uids,
                                                 gboolean delete_originals,
+                                                GPtrArray **transferred_uids,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       camel_imap_expunge_uids_resyncing
index cd6f74f..d94b522 100644 (file)
@@ -370,7 +370,7 @@ imap_entry_play (CamelOfflineJournal *journal,
 
                if (!camel_imap_transfer_resyncing (
                        journal->folder, imap_entry->uids, destination,
-                       &ret_uids, imap_entry->move, cancellable, error))
+                       imap_entry->move, &ret_uids, cancellable, error))
                        return -1;
 
                if (ret_uids) {
index bf5595a..02457cb 100644 (file)
@@ -278,7 +278,7 @@ imapx_search_by_expression (CamelFolder *folder, const gchar *expression, GError
 static gboolean
 imapx_append_message_sync (CamelFolder *folder,
                            CamelMimeMessage *message,
-                           const CamelMessageInfo *info,
+                           CamelMessageInfo *info,
                            gchar **appended_uid,
                            GCancellable *cancellable,
                            GError **error)
@@ -399,8 +399,8 @@ imapx_get_message_sync (CamelFolder *folder,
                msg = camel_mime_message_new ();
 
                g_mutex_lock (ifolder->stream_lock);
-               if (camel_data_wrapper_construct_from_stream_sync (
-                       (CamelDataWrapper *)msg, stream, cancellable, error) == -1) {
+               if (!camel_data_wrapper_construct_from_stream_sync (
+                       (CamelDataWrapper *)msg, stream, cancellable, error)) {
                        g_object_unref (msg);
                        msg = NULL;
                }
@@ -521,8 +521,8 @@ static gboolean
 imapx_transfer_messages_to_sync (CamelFolder *source,
                                  GPtrArray *uids,
                                  CamelFolder *dest,
-                                 GPtrArray **transferred_uids,
                                  gboolean delete_originals,
+                                 GPtrArray **transferred_uids,
                                  GCancellable *cancellable,
                                  GError **error)
 {
index f2bf917..2776d02 100644 (file)
@@ -3847,7 +3847,7 @@ imapx_job_scan_changes_done (CamelIMAPXServer *is,
 
                /* If we have any new messages, download their headers, but only a few (100?) at a time */
                if (fetch_new) {
-                       camel_operation_start (
+                       camel_operation_push_message (
                                job->cancellable,
                                _("Fetching summary information for new messages in %s"),
                                camel_folder_get_name (job->folder));
@@ -3889,7 +3889,7 @@ imapx_job_scan_changes_start (CamelIMAPXServer *is,
 {
        CamelIMAPXCommand *ic;
 
-       camel_operation_start (
+       camel_operation_push_message (
                job->cancellable,
                _("Scanning for changed messages in %s"),
                camel_folder_get_name (job->folder));
@@ -3974,7 +3974,7 @@ imapx_job_fetch_new_messages_start (CamelIMAPXServer *is,
        } else
                uid = g_strdup ("1");
 
-       camel_operation_start (
+       camel_operation_push_message (
                job->cancellable,
                _("Fetching summary information for new messages in %s"),
                camel_folder_get_name (folder));
index 57f322f..764b1ee 100644 (file)
@@ -114,7 +114,7 @@ maildir_folder_get_filename (CamelFolder *folder,
 static gboolean
 maildir_folder_append_message_sync (CamelFolder *folder,
                                     CamelMimeMessage *message,
-                                    const CamelMessageInfo *info,
+                                    CamelMessageInfo *info,
                                     gchar **appended_uid,
                                     GCancellable *cancellable,
                                     GError **error)
@@ -253,9 +253,9 @@ maildir_folder_get_message_sync (CamelFolder *folder,
        }
 
        message = camel_mime_message_new ();
-       if (camel_data_wrapper_construct_from_stream_sync (
+       if (!camel_data_wrapper_construct_from_stream_sync (
                (CamelDataWrapper *)message,
-               message_stream, cancellable, error) == -1) {
+               message_stream, cancellable, error)) {
                g_prefix_error (
                        error, _("Cannot get message %s from folder %s: "),
                        uid, lf->folder_path);
@@ -281,8 +281,8 @@ static gboolean
 maildir_folder_transfer_messages_to_sync (CamelFolder *source,
                                           GPtrArray *uids,
                                           CamelFolder *dest,
-                                          GPtrArray **transferred_uids,
                                           gboolean delete_originals,
+                                          GPtrArray **transferred_uids,
                                           GCancellable *cancellable,
                                           GError **error)
 {
@@ -293,7 +293,8 @@ maildir_folder_transfer_messages_to_sync (CamelFolder *source,
                CamelLocalFolder *lf = (CamelLocalFolder *) source;
                CamelLocalFolder *df = (CamelLocalFolder *) dest;
 
-               camel_operation_start (cancellable, _("Moving messages"));
+               camel_operation_push_message (
+                       cancellable, _("Moving messages"));
 
                camel_folder_freeze (dest);
                camel_folder_freeze (source);
@@ -346,7 +347,7 @@ maildir_folder_transfer_messages_to_sync (CamelFolder *source,
                camel_folder_thaw (source);
                camel_folder_thaw (dest);
 
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
        } else
                fallback = TRUE;
 
@@ -356,8 +357,8 @@ maildir_folder_transfer_messages_to_sync (CamelFolder *source,
                /* Chain up to parent's transfer_messages_to() method. */
                folder_class = CAMEL_FOLDER_CLASS (camel_maildir_folder_parent_class);
                return folder_class->transfer_messages_to_sync (
-                       source, uids, dest, transferred_uids,
-                       delete_originals, cancellable, error);
+                       source, uids, dest, delete_originals,
+                       transferred_uids, cancellable, error);
        }
 
        return TRUE;
index dca9bb8..7ad3e24 100644 (file)
@@ -552,7 +552,8 @@ maildir_summary_check (CamelLocalSummary *cls,
 
        d(printf("checking summary ...\n"));
 
-       camel_operation_start (cancellable, _("Checking folder consistency"));
+       camel_operation_push_message (
+               cancellable, _("Checking folder consistency"));
 
        /* scan the directory, check for mail files not in the index, or index entries that
           no longer exist */
@@ -565,7 +566,7 @@ maildir_summary_check (CamelLocalSummary *cls,
                        cls->folder_path, g_strerror (errno));
                g_free (cur);
                g_free (new);
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                g_mutex_unlock (((CamelMaildirSummary *) cls)->priv->summary_lock);
                return -1;
        }
@@ -642,9 +643,10 @@ maildir_summary_check (CamelLocalSummary *cls,
        g_hash_table_foreach (left, (GHFunc)remove_summary, &rd);
        g_hash_table_destroy (left);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
-       camel_operation_start (cancellable, _("Checking for new messages"));
+       camel_operation_push_message (
+               cancellable, _("Checking for new messages"));
 
        /* now, scan new for new messages, and copy them to cur, and so forth */
        dir = opendir (new);
@@ -704,7 +706,8 @@ maildir_summary_check (CamelLocalSummary *cls,
                        g_free (src);
                        g_free (dest);
                }
-               camel_operation_end (cancellable);
+
+               camel_operation_pop_message (cancellable);
                closedir (dir);
        }
 
@@ -736,7 +739,7 @@ maildir_summary_sync (CamelLocalSummary *cls,
        if (camel_local_summary_check (cls, changes, cancellable, error) == -1)
                return -1;
 
-       camel_operation_start (cancellable, _("Storing folder"));
+       camel_operation_push_message (cancellable, _("Storing folder"));
 
        camel_folder_summary_prepare_fetch_all ((CamelFolderSummary *)cls, error);
        count = camel_folder_summary_count ((CamelFolderSummary *)cls);
@@ -792,7 +795,7 @@ maildir_summary_sync (CamelLocalSummary *cls,
                camel_message_info_free (info);
        }
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        /* Chain up to parent's sync() method. */
        local_summary_class = CAMEL_LOCAL_SUMMARY_CLASS (camel_maildir_summary_parent_class);
index 32abf33..8174904 100644 (file)
@@ -138,7 +138,7 @@ fail:
 static gboolean
 mbox_folder_append_message_sync (CamelFolder *folder,
                                  CamelMimeMessage *message,
-                                 const CamelMessageInfo *info,
+                                 CamelMessageInfo *info,
                                  gchar **appended_uid,
                                  GCancellable *cancellable,
                                  GError **error)
@@ -380,8 +380,8 @@ retry:
        }
 
        message = camel_mime_message_new ();
-       if (camel_mime_part_construct_from_parser_sync (
-               (CamelMimePart *)message, parser, cancellable, error) == -1) {
+       if (!camel_mime_part_construct_from_parser_sync (
+               (CamelMimePart *)message, parser, cancellable, error)) {
                g_prefix_error (
                        error, _("Cannot get message %s from folder %s: "),
                        uid, lf->folder_path);
index 86d0562..5ce1476 100644 (file)
@@ -469,7 +469,7 @@ summary_update (CamelLocalSummary *cls,
 
        cls->index_force = FALSE;
 
-       camel_operation_start (cancellable, _("Storing folder"));
+       camel_operation_push_message (cancellable, _("Storing folder"));
 
        fd = g_open (cls->folder_path, O_LARGEFILE | O_RDONLY | O_BINARY, 0);
        if (fd == -1) {
@@ -479,7 +479,7 @@ summary_update (CamelLocalSummary *cls,
                        g_io_error_from_errno (errno),
                        _("Could not open folder: %s: %s"),
                        cls->folder_path, g_strerror (errno));
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                return -1;
        }
 
@@ -598,7 +598,7 @@ summary_update (CamelLocalSummary *cls,
                }
        }
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return ok;
 }
@@ -691,7 +691,7 @@ mbox_summary_sync_full (CamelMboxSummary *mbs,
 
        d(printf("performing full summary/sync\n"));
 
-       camel_operation_start (cancellable, _("Storing folder"));
+       camel_operation_push_message (cancellable, _("Storing folder"));
 
        fd = g_open (cls->folder_path, O_LARGEFILE | O_RDONLY | O_BINARY, 0);
        if (fd == -1) {
@@ -700,7 +700,7 @@ mbox_summary_sync_full (CamelMboxSummary *mbs,
                        g_io_error_from_errno (errno),
                        _("Could not open file: %s: %s"),
                        cls->folder_path, g_strerror (errno));
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                return -1;
        }
 
@@ -763,7 +763,7 @@ mbox_summary_sync_full (CamelMboxSummary *mbs,
        }
        tmpname = NULL;
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return 0;
  error:
@@ -776,7 +776,7 @@ mbox_summary_sync_full (CamelMboxSummary *mbs,
        if (tmpname)
                g_unlink (tmpname);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return -1;
 }
@@ -827,7 +827,7 @@ mbox_summary_sync_quick (CamelMboxSummary *mbs,
 
        d(printf("Performing quick summary sync\n"));
 
-       camel_operation_start (cancellable, _("Storing folder"));
+       camel_operation_push_message (cancellable, _("Storing folder"));
 
        fd = g_open (cls->folder_path, O_LARGEFILE|O_RDWR|O_BINARY, 0);
        if (fd == -1) {
@@ -837,7 +837,7 @@ mbox_summary_sync_quick (CamelMboxSummary *mbs,
                        _("Could not open file: %s: %s"),
                        cls->folder_path, g_strerror (errno));
 
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                return -1;
        }
 
@@ -960,7 +960,7 @@ mbox_summary_sync_quick (CamelMboxSummary *mbs,
        g_ptr_array_free (summary, TRUE);
        g_object_unref (mp);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
        camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
        return 0;
@@ -974,7 +974,7 @@ mbox_summary_sync_quick (CamelMboxSummary *mbs,
        if (info)
                camel_message_info_free ((CamelMessageInfo *)info);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
        camel_folder_summary_unlock (s, CAMEL_FOLDER_SUMMARY_SUMMARY_LOCK);
 
        return -1;
index a005a13..59147ef 100644 (file)
@@ -55,7 +55,7 @@ mh_folder_get_filename (CamelFolder *folder,
 static gboolean
 mh_folder_append_message_sync (CamelFolder *folder,
                                CamelMimeMessage *message,
-                               const CamelMessageInfo *info,
+                               CamelMessageInfo *info,
                                gchar **appended_uid,
                                GCancellable *cancellable,
                                GError **error)
@@ -171,9 +171,9 @@ mh_folder_get_message_sync (CamelFolder *folder,
        }
 
        message = camel_mime_message_new ();
-       if (camel_data_wrapper_construct_from_stream_sync (
+       if (!camel_data_wrapper_construct_from_stream_sync (
                (CamelDataWrapper *)message,
-               message_stream, cancellable, error) == -1) {
+               message_stream, cancellable, error)) {
                g_prefix_error (
                        error, _("Cannot get message %s from folder %s: "),
                        name, lf->folder_path);
index 30fc168..3dbf398 100644 (file)
@@ -128,7 +128,7 @@ spool_summary_sync_full (CamelMboxSummary *cls,
 
        d(printf("performing full summary/sync\n"));
 
-       camel_operation_start (cancellable, _("Storing folder"));
+       camel_operation_push_message (cancellable, _("Storing folder"));
 
        fd = open (((CamelLocalSummary *)cls)->folder_path, O_RDWR|O_LARGEFILE);
        if (fd == -1) {
@@ -138,7 +138,7 @@ spool_summary_sync_full (CamelMboxSummary *cls,
                        _("Could not open file: %s: %s"),
                        ((CamelLocalSummary *)cls)->folder_path,
                        g_strerror (errno));
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                return -1;
        }
 
@@ -286,7 +286,7 @@ spool_summary_sync_full (CamelMboxSummary *cls,
        if (tmpname[0] != '\0')
                unlink (tmpname);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return 0;
  error:
@@ -299,7 +299,7 @@ spool_summary_sync_full (CamelMboxSummary *cls,
        if (tmpname[0] != '\0')
                unlink (tmpname);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return -1;
 }
index 450b903..5c0e1b3 100644 (file)
@@ -414,7 +414,7 @@ nntp_folder_get_message_sync (CamelFolder *folder,
        }
 
        message = camel_mime_message_new ();
-       if (camel_data_wrapper_construct_from_stream_sync ((CamelDataWrapper *) message, stream, cancellable, error) == -1) {
+       if (!camel_data_wrapper_construct_from_stream_sync ((CamelDataWrapper *) message, stream, cancellable, error)) {
                g_prefix_error (error, _("Cannot get message %s: "), uid);
                g_object_unref (message);
                message = NULL;
index 1076171..68129a7 100644 (file)
@@ -241,7 +241,7 @@ add_range_xover (CamelNNTPSummary *cns,
        s = (CamelFolderSummary *)cns;
        summary_table = camel_folder_summary_get_hashtable (s);
 
-       camel_operation_start (
+       camel_operation_push_message (
                cancellable, _("%s: Scanning new messages"),
                ((CamelService *)store)->url->host);
 
@@ -250,7 +250,7 @@ add_range_xover (CamelNNTPSummary *cns,
                ret = camel_nntp_raw_command_auth (store, cancellable, error, &line, "xover %r", low, high);
 
        if (ret != 224) {
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                if (ret != -1)
                        g_set_error (
                                error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
@@ -321,7 +321,7 @@ add_range_xover (CamelNNTPSummary *cns,
                camel_header_raw_clear (&headers);
        }
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        camel_folder_summary_free_hashtable (summary_table);
 
@@ -352,7 +352,7 @@ add_range_head (CamelNNTPSummary *cns,
 
        mp = camel_mime_parser_new ();
 
-       camel_operation_start (
+       camel_operation_push_message (
                cancellable, _("%s: Scanning new messages"),
                ((CamelService *)store)->url->host);
 
@@ -426,7 +426,7 @@ ioerror:
        }
        g_object_unref (mp);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        camel_folder_summary_free_hashtable (summary_table);
 
index 390fd77..fce90e9 100644 (file)
@@ -338,7 +338,7 @@ pop3_folder_get_message_sync (CamelFolder *folder,
        /* Sigh, most of the crap in this function is so that the cancel button
           returns the proper exception code.  Sigh. */
 
-       camel_operation_start_transient (
+       camel_operation_push_message (
                cancellable, _("Retrieving POP message %d"), fi->id);
 
        /* If we have an oustanding retrieve message running, wait for that to complete
@@ -450,8 +450,8 @@ pop3_folder_get_message_sync (CamelFolder *folder,
        }
 
        message = camel_mime_message_new ();
-       if (camel_data_wrapper_construct_from_stream_sync (
-               CAMEL_DATA_WRAPPER (message), stream, cancellable, error) == -1) {
+       if (!camel_data_wrapper_construct_from_stream_sync (
+               CAMEL_DATA_WRAPPER (message), stream, cancellable, error)) {
                g_prefix_error (error, _("Cannot get message %s: "), uid);
                g_object_unref (message);
                message = NULL;
@@ -459,7 +459,7 @@ pop3_folder_get_message_sync (CamelFolder *folder,
 done:
        g_object_unref (stream);
 fail:
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return message;
 }
@@ -479,7 +479,8 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
        parent_store = camel_folder_get_parent_store (folder);
        pop3_store = CAMEL_POP3_STORE (parent_store);
 
-       camel_operation_start (cancellable, _("Retrieving POP summary"));
+       camel_operation_push_message (
+               cancellable, _("Retrieving POP summary"));
 
        pop3_folder->uids = g_ptr_array_new ();
        pop3_folder->uids_uid = g_hash_table_new (g_str_hash, g_str_equal);
@@ -528,7 +529,7 @@ pop3_folder_refresh_info_sync (CamelFolder *folder,
        /* dont need this anymore */
        g_hash_table_destroy (pop3_folder->uids_id);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return success;
 }
@@ -553,17 +554,22 @@ pop3_folder_synchronize_sync (CamelFolder *folder,
        if (pop3_store->delete_after && !expunge) {
                d(printf("%s(%d): pop3_store->delete_after = [%d], expunge=[%d]\n",
                         __FILE__, __LINE__, pop3_store->delete_after, expunge));
-               camel_operation_start (cancellable, _("Expunging old messages"));
+               camel_operation_push_message (
+                       cancellable, _("Expunging old messages"));
+
                camel_pop3_delete_old (
                        folder, pop3_store->delete_after,
                        cancellable, error);
+
+               camel_operation_pop_message (cancellable);
        }
 
        if (!expunge) {
                return TRUE;
        }
 
-       camel_operation_start (cancellable, _("Expunging deleted messages"));
+       camel_operation_push_message (
+               cancellable, _("Expunging deleted messages"));
 
        for (i = 0; i < pop3_folder->uids->len; i++) {
                fi = pop3_folder->uids->pdata[i];
@@ -602,7 +608,7 @@ pop3_folder_synchronize_sync (CamelFolder *folder,
                        cancellable, (i+1) * 100 / pop3_folder->uids->len);
        }
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        camel_pop3_store_expunge (pop3_store, error);
 
@@ -681,8 +687,8 @@ pop3_get_message_time_from_cache (CamelFolder *folder, const gchar *uid, time_t
                CamelMimeMessage *message;
 
                message = camel_mime_message_new ();
-               if (camel_data_wrapper_construct_from_stream_sync (
-                       (CamelDataWrapper *)message, stream, NULL, NULL) == -1) {
+               if (!camel_data_wrapper_construct_from_stream_sync (
+                       (CamelDataWrapper *)message, stream, NULL, NULL)) {
                        g_warning (_("Cannot get message %s: %s"), uid, g_strerror (errno));
                        g_object_unref (message);
                        message = NULL;
@@ -782,8 +788,6 @@ camel_pop3_delete_old (CamelFolder *folder,
                        cancellable, (i+1) * 100 / pop3_folder->uids->len);
        }
 
-       camel_operation_end (cancellable);
-
        camel_pop3_store_expunge (pop3_store, error);
 
        return 0;
index 9f17160..2b17ec0 100644 (file)
@@ -614,7 +614,7 @@ smtp_send_to_sync (CamelTransport *transport,
                return FALSE;
        }
 
-       camel_operation_start (cancellable, _("Sending message"));
+       camel_operation_push_message (cancellable, _("Sending message"));
 
        /* find out if the message has 8bit mime parts */
        has_8bit_parts = camel_mime_message_has_8bit_parts (message);
@@ -623,7 +623,7 @@ smtp_send_to_sync (CamelTransport *transport,
           you'll be sending an 8bit mime message at "MAIL FROM:" time. */
        if (!smtp_mail (
                smtp_transport, addr, has_8bit_parts, cancellable, error)) {
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                return FALSE;
        }
 
@@ -632,7 +632,7 @@ smtp_send_to_sync (CamelTransport *transport,
                g_set_error (
                        error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
                        _("Cannot send message: no recipients defined."));
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                return FALSE;
        }
 
@@ -645,28 +645,28 @@ smtp_send_to_sync (CamelTransport *transport,
                                error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
                                _("Cannot send message: "
                                  "one or more invalid recipients"));
-                       camel_operation_end (cancellable);
+                       camel_operation_pop_message (cancellable);
                        return FALSE;
                }
 
                enc = camel_internet_address_encode_address (NULL, NULL, addr);
                if (!smtp_rcpt (smtp_transport, enc, cancellable, error)) {
                        g_free (enc);
-                       camel_operation_end (cancellable);
+                       camel_operation_pop_message (cancellable);
                        return FALSE;
                }
                g_free (enc);
        }
 
        if (!smtp_data (smtp_transport, message, cancellable, error)) {
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                return FALSE;
        }
 
        /* reset the service for our next transfer session */
        smtp_rset (smtp_transport, cancellable, NULL);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return TRUE;
 }
@@ -1011,7 +1011,7 @@ smtp_helo (CamelSmtpTransport *transport,
                transport->authtypes = NULL;
        }
 
-       camel_operation_start_transient (cancellable, _("SMTP Greeting"));
+       camel_operation_push_message (cancellable, _("SMTP Greeting"));
 
        addr = transport->localaddr;
        addrlen = transport->localaddrlen;
@@ -1039,7 +1039,7 @@ smtp_helo (CamelSmtpTransport *transport,
                transport->ostream, cmdbuf, cancellable, error) == -1) {
                g_free (cmdbuf);
                g_prefix_error (error, _("HELO command failed: "));
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
 
                camel_service_disconnect_sync (
                        (CamelService *) transport, FALSE, NULL);
@@ -1057,14 +1057,14 @@ smtp_helo (CamelSmtpTransport *transport,
                if (respbuf == NULL) {
                        g_prefix_error (error, _("HELO command failed: "));
                        transport->connected = FALSE;
-                       camel_operation_end (cancellable);
+                       camel_operation_pop_message (cancellable);
                        return FALSE;
                }
                if (strncmp (respbuf, "250", 3)) {
                        smtp_set_error (
                                transport, respbuf, cancellable, error);
                        g_prefix_error (error, _("HELO command failed: "));
-                       camel_operation_end (cancellable);
+                       camel_operation_pop_message (cancellable);
                        g_free (respbuf);
                        return FALSE;
                }
@@ -1113,7 +1113,7 @@ smtp_helo (CamelSmtpTransport *transport,
        } while (*(respbuf+3) == '-'); /* if we got "250-" then loop again */
        g_free (respbuf);
 
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        return TRUE;
 }
@@ -1131,11 +1131,11 @@ smtp_auth (CamelSmtpTransport *transport,
 
        service = CAMEL_SERVICE (transport);
 
-       camel_operation_start_transient (cancellable, _("SMTP Authentication"));
+       camel_operation_push_message (cancellable, _("SMTP Authentication"));
 
        sasl = camel_sasl_new ("smtp", mech, service);
        if (!sasl) {
-               camel_operation_end (cancellable);
+               camel_operation_pop_message (cancellable);
                g_set_error (
                        error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
                        _("Error creating SASL authentication object."));
@@ -1242,7 +1242,7 @@ smtp_auth (CamelSmtpTransport *transport,
        }
 
        g_object_unref (sasl);
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        g_free (respbuf);
 
@@ -1258,7 +1258,7 @@ smtp_auth (CamelSmtpTransport *transport,
 
  lose:
        g_object_unref (sasl);
-       camel_operation_end (cancellable);
+       camel_operation_pop_message (cancellable);
 
        g_free (respbuf);
 
index eb472fe..d20d7a0 100644 (file)
       <title>Index of deprecated symbols</title>
       <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
     </index>
+    <index id="api-index-2.34" role="2.34">
+      <title>Index of new symbols in 2.34</title>
+      <xi:include href="xml/api-index-2.34.xml"><xi:fallback /></xi:include>
+    </index>
     <index id="api-index-2.32" role="2.32">
       <title>Index of new symbols in 2.32</title>
       <xi:include href="xml/api-index-2.32.xml"><xi:fallback /></xi:include>
index 0d18659..c80d562 100644 (file)
@@ -139,14 +139,26 @@ camel_cipher_validity_encrypt_t
 camel_cipher_validity_mode_t
 camel_cipher_context_new
 camel_cipher_context_get_session
-camel_cipher_id_to_hash
-camel_cipher_hash_to_id
-camel_cipher_sign_sync
-camel_cipher_verify_sync
-camel_cipher_encrypt_sync
-camel_cipher_decrypt_sync
-camel_cipher_import_keys_sync
-camel_cipher_export_keys_sync
+camel_cipher_context_id_to_hash
+camel_cipher_context_hash_to_id
+camel_cipher_context_sign_sync
+camel_cipher_context_sign
+camel_cipher_context_sign_finish
+camel_cipher_context_verify_sync
+camel_cipher_context_verify
+camel_cipher_context_verify_finish
+camel_cipher_context_encrypt_sync
+camel_cipher_context_encrypt
+camel_cipher_context_encrypt_finish
+camel_cipher_context_decrypt_sync
+camel_cipher_context_decrypt
+camel_cipher_context_decrypt_finish
+camel_cipher_context_import_keys_sync
+camel_cipher_context_import_keys
+camel_cipher_context_import_keys_finish
+camel_cipher_context_export_keys_sync
+camel_cipher_context_export_keys
+camel_cipher_context_export_keys_finish
 camel_cipher_validity_new
 camel_cipher_validity_init
 camel_cipher_validity_get_valid
@@ -210,8 +222,14 @@ camel_data_wrapper_get_mime_type_field
 camel_data_wrapper_set_mime_type_field
 camel_data_wrapper_is_offline
 camel_data_wrapper_write_to_stream_sync
+camel_data_wrapper_write_to_stream
+camel_data_wrapper_write_to_stream_finish
 camel_data_wrapper_decode_to_stream_sync
+camel_data_wrapper_decode_to_stream
+camel_data_wrapper_decode_to_stream_finish
 camel_data_wrapper_construct_from_stream_sync
+camel_data_wrapper_construct_from_stream
+camel_data_wrapper_construct_from_stream_finish
 CamelDataWrapperLock
 camel_data_wrapper_lock
 camel_data_wrapper_unlock
@@ -467,12 +485,26 @@ camel_folder_free_shallow
 camel_folder_free_deep
 camel_folder_get_filename
 camel_folder_append_message_sync
+camel_folder_append_message
+camel_folder_append_message_finish
 camel_folder_expunge_sync
+camel_folder_expunge
+camel_folder_expunge_finish
 camel_folder_get_message_sync
+camel_folder_get_message
+camel_folder_get_message_finish
 camel_folder_refresh_info_sync
+camel_folder_refresh_info
+camel_folder_refresh_info_finish
 camel_folder_synchronize_sync
+camel_folder_synchronize
+camel_folder_synchronize_finish
 camel_folder_synchronize_message_sync
+camel_folder_synchronize_message
+camel_folder_synchronize_message_finish
 camel_folder_transfer_messages_to_sync
+camel_folder_transfer_messages_to
+camel_folder_transfer_messages_to_finish
 camel_folder_change_info_new
 camel_folder_change_info_clear
 camel_folder_change_info_free
@@ -1244,6 +1276,7 @@ camel_mime_message_get_part_by_content_id
 camel_mime_message_build_mbox_from
 camel_mime_message_has_attachment
 camel_mime_message_dump
+camel_mime_message_build_preview
 <SUBSECTION Standard>
 CAMEL_MIME_MESSAGE
 CAMEL_IS_MIME_MESSAGE
@@ -1327,10 +1360,10 @@ camel_mime_part_get_content_languages
 camel_mime_part_set_content_type
 camel_mime_part_get_content_type
 camel_mime_part_construct_from_parser_sync
+camel_mime_part_construct_from_parser
+camel_mime_part_construct_from_parser_finish
 camel_mime_part_set_content
-camel_mime_part_get_content_size
 camel_mime_part_construct_content_from_parser
-camel_mime_message_build_preview
 <SUBSECTION Standard>
 CAMEL_MIME_PART
 CAMEL_IS_MIME_PART
@@ -1487,6 +1520,8 @@ CamelOfflineFolder
 camel_offline_folder_get_offline_sync
 camel_offline_folder_set_offline_sync
 camel_offline_folder_downsync_sync
+camel_offline_folder_downsync
+camel_offline_folder_downsync_finish
 <SUBSECTION Standard>
 CAMEL_OFFLINE_FOLDER
 CAMEL_IS_OFFLINE_FOLDER
@@ -1599,10 +1634,9 @@ camel_operation_uncancel
 camel_operation_cancel_check
 camel_operation_cancel_fd
 camel_operation_cancel_prfd
-camel_operation_start
-camel_operation_start_transient
+camel_operation_push_message
+camel_operation_pop_message
 camel_operation_progress
-camel_operation_end
 <SUBSECTION Standard>
 CAMEL_OPERATION
 CAMEL_IS_OPERATION
@@ -1839,7 +1873,11 @@ camel_sasl_get_mechanism
 camel_sasl_get_service
 camel_sasl_get_service_name
 camel_sasl_challenge_sync
+camel_sasl_challenge
+camel_sasl_challenge_finish
 camel_sasl_challenge_base64_sync
+camel_sasl_challenge_base64
+camel_sasl_challenge_base64_finish
 camel_sasl_authtype_list
 camel_sasl_authtype
 <SUBSECTION Standard>
@@ -2128,17 +2166,41 @@ CamelStoreLock
 camel_store_lock
 camel_store_unlock
 camel_store_get_folder_sync
+camel_store_get_folder
+camel_store_get_folder_finish
 camel_store_get_folder_info_sync
+camel_store_get_folder_info
+camel_store_get_folder_info_finish
 camel_store_get_inbox_folder_sync
+camel_store_get_inbox_folder
+camel_store_get_inbox_folder_finish
 camel_store_get_junk_folder_sync
+camel_store_get_junk_folder
+camel_store_get_junk_folder_finish
 camel_store_get_trash_folder_sync
+camel_store_get_trash_folder
+camel_store_get_trash_folder_finish
 camel_store_create_folder_sync
+camel_store_create_folder
+camel_store_create_folder_finish
 camel_store_delete_folder_sync
+camel_store_delete_folder
+camel_store_delete_folder_finish
 camel_store_rename_folder_sync
+camel_store_rename_folder
+camel_store_rename_folder_finish
 camel_store_subscribe_folder_sync
+camel_store_subscribe_folder
+camel_store_subscribe_folder_finish
 camel_store_unsubscribe_folder_sync
+camel_store_unsubscribe_folder
+camel_store_unsubscribe_folder_finish
 camel_store_synchronize_sync
+camel_store_synchronize
+camel_store_synchronize_finish
 camel_store_noop_sync
+camel_store_noop
+camel_store_noop_finish
 <SUBSECTION Standard>
 CAMEL_STORE
 CAMEL_IS_STORE
@@ -2459,10 +2521,12 @@ camel_text_index_name_get_type
 <FILE>camel-transport</FILE>
 <TITLE>CamelTransport</TITLE>
 CamelTransport
-camel_transport_send_to_sync
 CamelTransportLock
 camel_transport_lock
 camel_transport_unlock
+camel_transport_send_to_sync
+camel_transport_send_to
+camel_transport_send_to_finish
 <SUBSECTION Standard>
 CAMEL_TRANSPORT
 CAMEL_IS_TRANSPORT
index 1068c8f..aa30635 100644 (file)
@@ -116,7 +116,7 @@ CamelCipherContext
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_cipher_id_to_hash ##### -->
+<!-- ##### FUNCTION camel_cipher_context_id_to_hash ##### -->
 <para>
 
 </para>
@@ -126,7 +126,7 @@ CamelCipherContext
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_cipher_hash_to_id ##### -->
+<!-- ##### FUNCTION camel_cipher_context_hash_to_id ##### -->
 <para>
 
 </para>
@@ -136,7 +136,7 @@ CamelCipherContext
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_cipher_sign_sync ##### -->
+<!-- ##### FUNCTION camel_cipher_context_sign_sync ##### -->
 <para>
 
 </para>
@@ -151,19 +151,70 @@ CamelCipherContext
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_cipher_verify_sync ##### -->
+<!-- ##### FUNCTION camel_cipher_context_sign ##### -->
 <para>
 
 </para>
 
 @context: 
+@userid: 
+@hash: 
 @ipart: 
+@opart: 
+@io_priority: 
 @cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_cipher_context_sign_finish ##### -->
+<para>
+
+</para>
+
+@context: 
+@result: 
+@error: 
+@Returns: 
+
+
+<!-- ##### FUNCTION camel_cipher_context_verify_sync ##### -->
+<para>
+
+</para>
+
+@context: 
+@ipart: 
+@cancellable: 
+@error: 
+@Returns: 
+
+
+<!-- ##### FUNCTION camel_cipher_context_verify ##### -->
+<para>
+
+</para>
+
+@context: 
+@ipart: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_cipher_context_verify_finish ##### -->
+<para>
+
+</para>
+
+@context: 
+@result: 
 @error: 
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_cipher_encrypt_sync ##### -->
+<!-- ##### FUNCTION camel_cipher_context_encrypt_sync ##### -->
 <para>
 
 </para>
@@ -178,7 +229,34 @@ CamelCipherContext
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_cipher_decrypt_sync ##### -->
+<!-- ##### FUNCTION camel_cipher_context_encrypt ##### -->
+<para>
+
+</para>
+
+@context: 
+@userid: 
+@recipients: 
+@ipart: 
+@opart: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_cipher_context_encrypt_finish ##### -->
+<para>
+
+</para>
+
+@context: 
+@result: 
+@error: 
+@Returns: 
+
+
+<!-- ##### FUNCTION camel_cipher_context_decrypt_sync ##### -->
 <para>
 
 </para>
@@ -191,19 +269,68 @@ CamelCipherContext
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_cipher_import_keys_sync ##### -->
+<!-- ##### FUNCTION camel_cipher_context_decrypt ##### -->
+<para>
+
+</para>
+
+@context: 
+@ipart: 
+@opart: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_cipher_context_decrypt_finish ##### -->
+<para>
+
+</para>
+
+@context: 
+@result: 
+@error: 
+@Returns: 
+
+
+<!-- ##### FUNCTION camel_cipher_context_import_keys_sync ##### -->
+<para>
+
+</para>
+
+@context: 
+@istream: 
+@cancellable: 
+@error: 
+@Returns: 
+
+
+<!-- ##### FUNCTION camel_cipher_context_import_keys ##### -->
 <para>
 
 </para>
 
 @context: 
 @istream: 
+@io_priority: 
 @cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_cipher_context_import_keys_finish ##### -->
+<para>
+
+</para>
+
+@context: 
+@result: 
 @error: 
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_cipher_export_keys_sync ##### -->
+<!-- ##### FUNCTION camel_cipher_context_export_keys_sync ##### -->
 <para>
 
 </para>
@@ -216,6 +343,31 @@ CamelCipherContext
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_cipher_context_export_keys ##### -->
+<para>
+
+</para>
+
+@context: 
+@keys: 
+@ostream: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_cipher_context_export_keys_finish ##### -->
+<para>
+
+</para>
+
+@context: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_cipher_validity_new ##### -->
 <para>
 
@@ -528,6 +680,44 @@ CamelCipherContext
 @gpointer cert_data: 
 @gpointer cert_data:
 @gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
+@gpointer cert_data:
+@gpointer cert_data: 
 @gpointer cert_data: 
 
 
index a27a941..cb746fa 100644 (file)
@@ -92,6 +92,30 @@ CamelDataWrapper
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_data_wrapper_write_to_stream ##### -->
+<para>
+
+</para>
+
+@data_wrapper: 
+@stream: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_data_wrapper_write_to_stream_finish ##### -->
+<para>
+
+</para>
+
+@data_wrapper: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_data_wrapper_decode_to_stream_sync ##### -->
 <para>
 
@@ -104,6 +128,30 @@ CamelDataWrapper
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_data_wrapper_decode_to_stream ##### -->
+<para>
+
+</para>
+
+@data_wrapper: 
+@stream: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_data_wrapper_decode_to_stream_finish ##### -->
+<para>
+
+</para>
+
+@data_wrapper: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_data_wrapper_construct_from_stream_sync ##### -->
 <para>
 
@@ -116,6 +164,30 @@ CamelDataWrapper
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_data_wrapper_construct_from_stream ##### -->
+<para>
+
+</para>
+
+@data_wrapper: 
+@stream: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_data_wrapper_construct_from_stream_finish ##### -->
+<para>
+
+</para>
+
+@data_wrapper: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### ENUM CamelDataWrapperLock ##### -->
 <para>
 
index 08e58fa..be18b4d 100644 (file)
@@ -82,9 +82,9 @@ CamelDB
 </para>
 
 @Param1: 
-@Varargs
+@Param2
 @Param3: 
-@Varargs
+@Param4
 @Param5: 
 @Returns: 
 
index 5cdadca..9769acc 100644 (file)
@@ -718,6 +718,7 @@ CamelFolderSummary
 </para>
 
 @info: 
+@Returns: 
 
 
 <!-- ##### FUNCTION camel_message_info_new_from_header ##### -->
index 99b6483..4e52502 100644 (file)
@@ -648,6 +648,32 @@ CamelFolder
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_folder_append_message ##### -->
+<para>
+
+</para>
+
+@folder: 
+@message: 
+@info: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_folder_append_message_finish ##### -->
+<para>
+
+</para>
+
+@folder: 
+@result: 
+@appended_uid: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_folder_expunge_sync ##### -->
 <para>
 
@@ -659,18 +685,65 @@ CamelFolder
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_folder_expunge ##### -->
+<para>
+
+</para>
+
+@folder: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_folder_expunge_finish ##### -->
+<para>
+
+</para>
+
+@folder: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_folder_get_message_sync ##### -->
 <para>
 
 </para>
 
 @folder: 
-@uid: 
+@message_uid: 
 @cancellable: 
 @error: 
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_folder_get_message ##### -->
+<para>
+
+</para>
+
+@folder: 
+@message_uid: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_folder_get_message_finish ##### -->
+<para>
+
+</para>
+
+@folder: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_folder_refresh_info_sync ##### -->
 <para>
 
@@ -682,6 +755,29 @@ CamelFolder
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_folder_refresh_info ##### -->
+<para>
+
+</para>
+
+@folder: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_folder_refresh_info_finish ##### -->
+<para>
+
+</para>
+
+@folder: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_folder_synchronize_sync ##### -->
 <para>
 
@@ -694,29 +790,104 @@ CamelFolder
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_folder_synchronize ##### -->
+<para>
+
+</para>
+
+@folder: 
+@expunge: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_folder_synchronize_finish ##### -->
+<para>
+
+</para>
+
+@folder: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_folder_synchronize_message_sync ##### -->
 <para>
 
 </para>
 
 @folder: 
-@uid: 
+@message_uid: 
 @cancellable: 
 @error: 
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_folder_synchronize_message ##### -->
+<para>
+
+</para>
+
+@folder: 
+@message_uid: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_folder_synchronize_message_finish ##### -->
+<para>
+
+</para>
+
+@folder: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_folder_transfer_messages_to_sync ##### -->
 <para>
 
 </para>
 
 @source: 
-@uids: 
-@dest: 
+@message_uids: 
+@destination: 
+@delete_originals: 
 @transferred_uids: 
+@cancellable: 
+@error: 
+@Returns: 
+
+
+<!-- ##### FUNCTION camel_folder_transfer_messages_to ##### -->
+<para>
+
+</para>
+
+@source: 
+@message_uids: 
+@destination: 
 @delete_originals: 
+@io_priority: 
 @cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_folder_transfer_messages_to_finish ##### -->
+<para>
+
+</para>
+
+@source: 
+@result: 
+@transferred_uids: 
 @error: 
 @Returns: 
 
index 8b91f07..dd7e37b 100644 (file)
@@ -284,7 +284,17 @@ CamelMimeMessage
 
 </para>
 
-@msg
+@message
 @body: 
 
 
+<!-- ##### FUNCTION camel_mime_message_build_preview ##### -->
+<para>
+
+</para>
+
+@mime_part: 
+@info: 
+@Returns: 
+
+
index 55cad4b..28c7905 100644 (file)
@@ -238,45 +238,50 @@ CamelMimePart
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_mime_part_set_content ##### -->
+<!-- ##### FUNCTION camel_mime_part_construct_from_parser ##### -->
 <para>
 
 </para>
 
 @mime_part: 
-@data: 
-@length: 
-@type: 
+@parser: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
 
 
-<!-- ##### FUNCTION camel_mime_part_get_content_size ##### -->
+<!-- ##### FUNCTION camel_mime_part_construct_from_parser_finish ##### -->
 <para>
 
 </para>
 
 @mime_part: 
+@result: 
+@error: 
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_mime_part_construct_content_from_parser ##### -->
+<!-- ##### FUNCTION camel_mime_part_set_content ##### -->
 <para>
 
 </para>
 
 @mime_part: 
-@mp: 
-@cancellable: 
-@error: 
-@Returns: 
+@data: 
+@length: 
+@type: 
 
 
-<!-- ##### FUNCTION camel_mime_message_build_preview ##### -->
+<!-- ##### FUNCTION camel_mime_part_construct_content_from_parser ##### -->
 <para>
 
 </para>
 
 @mime_part: 
-@info: 
+@mp: 
+@cancellable: 
+@error: 
 @Returns: 
 
 
index e84bfae..6c51d3a 100644 (file)
@@ -36,7 +36,7 @@ CamelOfflineFolder
 
 </para>
 
-@offline
+@folder
 @Returns: 
 
 
@@ -45,7 +45,7 @@ CamelOfflineFolder
 
 </para>
 
-@offline
+@folder
 @offline_sync: 
 
 
@@ -54,10 +54,34 @@ CamelOfflineFolder
 
 </para>
 
-@offline
+@folder
 @expression: 
 @cancellable: 
 @error: 
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_offline_folder_downsync ##### -->
+<para>
+
+</para>
+
+@folder: 
+@expression: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_offline_folder_downsync_finish ##### -->
+<para>
+
+</para>
+
+@folder: 
+@result: 
+@error: 
+@Returns: 
+
+
index 3660bc7..1555b1b 100644 (file)
@@ -80,24 +80,22 @@ camel-operation
 @Returns: 
 
 
-<!-- ##### FUNCTION camel_operation_start ##### -->
+<!-- ##### FUNCTION camel_operation_push_message ##### -->
 <para>
 
 </para>
 
 @cancellable: 
-@what: 
+@format: 
 @Varargs: 
 
 
-<!-- ##### FUNCTION camel_operation_start_transient ##### -->
+<!-- ##### FUNCTION camel_operation_pop_message ##### -->
 <para>
 
 </para>
 
 @cancellable: 
-@what: 
-@Varargs: 
 
 
 <!-- ##### FUNCTION camel_operation_progress ##### -->
@@ -106,14 +104,6 @@ camel-operation
 </para>
 
 @cancellable: 
-@pc: 
-
-
-<!-- ##### FUNCTION camel_operation_end ##### -->
-<para>
-
-</para>
-
-@cancellable: 
+@percent: 
 
 
index 9d4c81f..ab15851 100644 (file)
@@ -114,6 +114,30 @@ CamelSasl
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_sasl_challenge ##### -->
+<para>
+
+</para>
+
+@sasl: 
+@token: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_sasl_challenge_finish ##### -->
+<para>
+
+</para>
+
+@sasl: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_sasl_challenge_base64_sync ##### -->
 <para>
 
@@ -126,6 +150,30 @@ CamelSasl
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_sasl_challenge_base64 ##### -->
+<para>
+
+</para>
+
+@sasl: 
+@token: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_sasl_challenge_base64_finish ##### -->
+<para>
+
+</para>
+
+@sasl: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_sasl_authtype_list ##### -->
 <para>
 
index 7976bfc..aa399d9 100644 (file)
@@ -561,6 +561,31 @@ CamelStore
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_store_get_folder ##### -->
+<para>
+
+</para>
+
+@store: 
+@folder_name: 
+@flags: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_store_get_folder_finish ##### -->
+<para>
+
+</para>
+
+@store: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_store_get_folder_info_sync ##### -->
 <para>
 
@@ -574,6 +599,31 @@ CamelStore
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_store_get_folder_info ##### -->
+<para>
+
+</para>
+
+@store: 
+@top: 
+@flags: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_store_get_folder_info_finish ##### -->
+<para>
+
+</para>
+
+@store: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_store_get_inbox_folder_sync ##### -->
 <para>
 
@@ -585,6 +635,29 @@ CamelStore
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_store_get_inbox_folder ##### -->
+<para>
+
+</para>
+
+@store: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_store_get_inbox_folder_finish ##### -->
+<para>
+
+</para>
+
+@store: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_store_get_junk_folder_sync ##### -->
 <para>
 
@@ -596,6 +669,29 @@ CamelStore
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_store_get_junk_folder ##### -->
+<para>
+
+</para>
+
+@store: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_store_get_junk_folder_finish ##### -->
+<para>
+
+</para>
+
+@store: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_store_get_trash_folder_sync ##### -->
 <para>
 
@@ -607,6 +703,29 @@ CamelStore
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_store_get_trash_folder ##### -->
+<para>
+
+</para>
+
+@store: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_store_get_trash_folder_finish ##### -->
+<para>
+
+</para>
+
+@store: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_store_create_folder_sync ##### -->
 <para>
 
@@ -620,6 +739,31 @@ CamelStore
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_store_create_folder ##### -->
+<para>
+
+</para>
+
+@store: 
+@parent_name: 
+@folder_name: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_store_create_folder_finish ##### -->
+<para>
+
+</para>
+
+@store: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_store_delete_folder_sync ##### -->
 <para>
 
@@ -632,15 +776,64 @@ CamelStore
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_store_delete_folder ##### -->
+<para>
+
+</para>
+
+@store: 
+@folder_name: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_store_delete_folder_finish ##### -->
+<para>
+
+</para>
+
+@store: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_store_rename_folder_sync ##### -->
 <para>
 
 </para>
 
 @store: 
-@old_namein: 
+@old_name: 
+@new_name: 
+@cancellable: 
+@error: 
+@Returns: 
+
+
+<!-- ##### FUNCTION camel_store_rename_folder ##### -->
+<para>
+
+</para>
+
+@store: 
+@old_name: 
 @new_name: 
+@io_priority: 
 @cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_store_rename_folder_finish ##### -->
+<para>
+
+</para>
+
+@store: 
+@result: 
 @error: 
 @Returns: 
 
@@ -657,6 +850,30 @@ CamelStore
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_store_subscribe_folder ##### -->
+<para>
+
+</para>
+
+@store: 
+@folder_name: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_store_subscribe_folder_finish ##### -->
+<para>
+
+</para>
+
+@store: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_store_unsubscribe_folder_sync ##### -->
 <para>
 
@@ -669,6 +886,30 @@ CamelStore
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_store_unsubscribe_folder ##### -->
+<para>
+
+</para>
+
+@store: 
+@folder_name: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_store_unsubscribe_folder_finish ##### -->
+<para>
+
+</para>
+
+@store: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_store_synchronize_sync ##### -->
 <para>
 
@@ -681,6 +922,30 @@ CamelStore
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_store_synchronize ##### -->
+<para>
+
+</para>
+
+@store: 
+@expunge: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_store_synchronize_finish ##### -->
+<para>
+
+</para>
+
+@store: 
+@result: 
+@error: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_store_noop_sync ##### -->
 <para>
 
@@ -692,3 +957,26 @@ CamelStore
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_store_noop ##### -->
+<para>
+
+</para>
+
+@store: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
+
+
+<!-- ##### FUNCTION camel_store_noop_finish ##### -->
+<para>
+
+</para>
+
+@store: 
+@result: 
+@error: 
+@Returns: 
+
+
index c6bd743..ba5ff96 100644 (file)
@@ -26,6 +26,31 @@ CamelTransport
 </para>
 
 
+<!-- ##### ENUM CamelTransportLock ##### -->
+<para>
+
+</para>
+
+@CAMEL_TRANSPORT_SEND_LOCK: 
+
+<!-- ##### FUNCTION camel_transport_lock ##### -->
+<para>
+
+</para>
+
+@transport: 
+@lock: 
+
+
+<!-- ##### FUNCTION camel_transport_unlock ##### -->
+<para>
+
+</para>
+
+@transport: 
+@lock: 
+
+
 <!-- ##### FUNCTION camel_transport_send_to_sync ##### -->
 <para>
 
@@ -40,28 +65,29 @@ CamelTransport
 @Returns: 
 
 
-<!-- ##### ENUM CamelTransportLock ##### -->
-<para>
-
-</para>
-
-@CAMEL_TRANSPORT_SEND_LOCK: 
-
-<!-- ##### FUNCTION camel_transport_lock ##### -->
+<!-- ##### FUNCTION camel_transport_send_to ##### -->
 <para>
 
 </para>
 
 @transport: 
-@lock: 
+@message: 
+@from: 
+@recipients: 
+@io_priority: 
+@cancellable: 
+@callback: 
+@user_data: 
 
 
-<!-- ##### FUNCTION camel_transport_unlock ##### -->
+<!-- ##### FUNCTION camel_transport_send_to_finish ##### -->
 <para>
 
 </para>
 
 @transport: 
-@lock: 
+@result: 
+@error: 
+@Returns: 
 
 
index 152229e..cadb274 100644 (file)
@@ -4522,6 +4522,18 @@ streams
 @error: 
 @Returns: 
 
+<!-- ##### FUNCTION camel_cipher_decrypt_sync ##### -->
+<para>
+
+</para>
+
+@context: 
+@ipart: 
+@opart: 
+@cancellable: 
+@error: 
+@Returns: 
+
 <!-- ##### FUNCTION camel_cipher_encrypt ##### -->
 <para>
 
@@ -4536,6 +4548,20 @@ streams
 @error: 
 @Returns: 
 
+<!-- ##### FUNCTION camel_cipher_encrypt_sync ##### -->
+<para>
+
+</para>
+
+@context: 
+@userid: 
+@recipients: 
+@ipart: 
+@opart: 
+@cancellable: 
+@error: 
+@Returns: 
+
 <!-- ##### FUNCTION camel_cipher_export_keys ##### -->
 <para>
 
@@ -4548,96 +4574,129 @@ streams
 @error: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_cipher_import_keys ##### -->
+<!-- ##### FUNCTION camel_cipher_export_keys_sync ##### -->
 <para>
 
 </para>
 
 @context: 
-@istream: 
+@keys: 
+@ostream: 
 @cancellable: 
 @error: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_cipher_sign ##### -->
+<!-- ##### FUNCTION camel_cipher_hash_to_id ##### -->
 <para>
 
 </para>
 
 @context: 
-@userid: 
 @hash: 
-@ipart: 
-@opart: 
-@cancellable: 
-@error: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_cipher_verify ##### -->
+<!-- ##### FUNCTION camel_cipher_id_to_hash ##### -->
 <para>
 
 </para>
 
 @context: 
-@ipart: 
+@id: 
+@Returns: 
+
+<!-- ##### FUNCTION camel_cipher_import_keys ##### -->
+<para>
+
+</para>
+
+@context: 
+@istream: 
 @cancellable: 
 @error: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_data_cache_clear ##### -->
+<!-- ##### FUNCTION camel_cipher_import_keys_sync ##### -->
 <para>
 
 </para>
 
-@cache: 
-@path: 
-@ex: 
+@context: 
+@istream: 
+@cancellable: 
+@error: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_data_cache_rename ##### -->
+<!-- ##### FUNCTION camel_cipher_sign ##### -->
 <para>
 
 </para>
 
-@cache: 
-@old: 
-@new: 
-@ex: 
+@context: 
+@userid: 
+@hash: 
+@ipart: 
+@opart: 
+@cancellable: 
+@error: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_data_wrapper_construct_from_stream ##### -->
+<!-- ##### FUNCTION camel_cipher_sign_sync ##### -->
 <para>
 
 </para>
 
-@data_wrapper: 
-@stream: 
+@context: 
+@userid: 
+@hash: 
+@ipart: 
+@opart: 
 @cancellable: 
 @error: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_data_wrapper_decode_to_stream ##### -->
+<!-- ##### FUNCTION camel_cipher_verify ##### -->
 <para>
 
 </para>
 
-@data_wrapper
-@stream
+@context
+@ipart
 @cancellable: 
 @error: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_data_wrapper_write_to_stream ##### -->
+<!-- ##### FUNCTION camel_cipher_verify_sync ##### -->
 <para>
 
 </para>
 
-@data_wrapper
-@stream
+@context
+@ipart
 @cancellable: 
 @error: 
 @Returns: 
 
+<!-- ##### FUNCTION camel_data_cache_clear ##### -->
+<para>
+
+</para>
+
+@cache: 
+@path: 
+@ex: 
+@Returns: 
+
+<!-- ##### FUNCTION camel_data_cache_rename ##### -->
+<para>
+
+</para>
+
+@cache: 
+@old: 
+@new: 
+@ex: 
+@Returns: 
+
 <!-- ##### FUNCTION camel_digest_folder_new ##### -->
 <para>
 
@@ -4786,19 +4845,6 @@ streams
 @n: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_folder_append_message ##### -->
-<para>
-
-</para>
-
-@folder: 
-@message: 
-@info: 
-@appended_uid: 
-@cancellable: 
-@error: 
-@Returns: 
-
 <!-- ##### FUNCTION camel_folder_construct ##### -->
 <para>
 
@@ -4809,37 +4855,6 @@ streams
 @full_name: 
 @name: 
 
-<!-- ##### FUNCTION camel_folder_expunge ##### -->
-<para>
-
-</para>
-
-@folder: 
-@cancellable: 
-@error: 
-@Returns: 
-
-<!-- ##### FUNCTION camel_folder_get_message ##### -->
-<para>
-
-</para>
-
-@folder: 
-@uid: 
-@cancellable: 
-@error: 
-@Returns: 
-
-<!-- ##### FUNCTION camel_folder_refresh_info ##### -->
-<para>
-
-</para>
-
-@folder: 
-@cancellable: 
-@error: 
-@Returns: 
-
 <!-- ##### FUNCTION camel_folder_summary_array_free ##### -->
 <para>
 
@@ -4912,20 +4927,6 @@ streams
 @error: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_folder_transfer_messages_to ##### -->
-<para>
-
-</para>
-
-@source: 
-@uids: 
-@dest: 
-@transferred_uids: 
-@delete_originals: 
-@cancellable: 
-@error: 
-@Returns: 
-
 <!-- ##### FUNCTION camel_groupwise_journal_append ##### -->
 <para>
 
@@ -6808,17 +6809,6 @@ streams
 @stream: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_mime_part_construct_from_parser ##### -->
-<para>
-
-</para>
-
-@mime_part: 
-@parser: 
-@cancellable: 
-@error: 
-@Returns: 
-
 <!-- ##### FUNCTION camel_mime_part_get_content_MD5 ##### -->
 <para>
 
@@ -7480,17 +7470,6 @@ streams
 
 @Param1: 
 
-<!-- ##### FUNCTION camel_offline_folder_downsync ##### -->
-<para>
-
-</para>
-
-@offline: 
-@expression: 
-@cancellable: 
-@error: 
-@Returns: 
-
 <!-- ##### FUNCTION camel_offline_store_get_network_state ##### -->
 <para>
 
@@ -7535,6 +7514,13 @@ streams
 
 @cc: 
 
+<!-- ##### FUNCTION camel_operation_end ##### -->
+<para>
+
+</para>
+
+@cancellable: 
+
 <!-- ##### FUNCTION camel_operation_mute ##### -->
 <para>
 
@@ -7573,6 +7559,24 @@ streams
 @void: 
 @Returns: 
 
+<!-- ##### FUNCTION camel_operation_start ##### -->
+<para>
+
+</para>
+
+@cancellable: 
+@what: 
+@Varargs: 
+
+<!-- ##### FUNCTION camel_operation_start_transient ##### -->
+<para>
+
+</para>
+
+@cancellable: 
+@what: 
+@Varargs: 
+
 <!-- ##### ENUM camel_operation_status_t ##### -->
 <para>
 
@@ -7802,28 +7806,6 @@ streams
 @sasl: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_sasl_challenge ##### -->
-<para>
-
-</para>
-
-@sasl: 
-@token: 
-@cancellable: 
-@error: 
-@Returns: 
-
-<!-- ##### FUNCTION camel_sasl_challenge_base64 ##### -->
-<para>
-
-</para>
-
-@sasl: 
-@token: 
-@cancellable: 
-@error: 
-@Returns: 
-
 <!-- ##### FUNCTION camel_search_build_match_regex ##### -->
 <para>
 
@@ -8096,53 +8078,6 @@ streams
 @xevline: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_store_create_folder ##### -->
-<para>
-
-</para>
-
-@store: 
-@parent_name: 
-@folder_name: 
-@cancellable: 
-@error: 
-@Returns: 
-
-<!-- ##### FUNCTION camel_store_delete_folder ##### -->
-<para>
-
-</para>
-
-@store: 
-@folder_name: 
-@cancellable: 
-@error: 
-@Returns: 
-
-<!-- ##### FUNCTION camel_store_get_folder ##### -->
-<para>
-
-</para>
-
-@store: 
-@folder_name: 
-@flags: 
-@cancellable: 
-@error: 
-@Returns: 
-
-<!-- ##### FUNCTION camel_store_get_folder_info ##### -->
-<para>
-
-</para>
-
-@store: 
-@top: 
-@flags: 
-@cancellable: 
-@error: 
-@Returns: 
-
 <!-- ##### FUNCTION camel_store_get_inbox ##### -->
 <para>
 
@@ -8173,39 +8108,6 @@ streams
 @error: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_store_noop ##### -->
-<para>
-
-</para>
-
-@store: 
-@cancellable: 
-@error: 
-@Returns: 
-
-<!-- ##### FUNCTION camel_store_rename_folder ##### -->
-<para>
-
-</para>
-
-@store: 
-@old_namein: 
-@new_name: 
-@cancellable: 
-@error: 
-@Returns: 
-
-<!-- ##### FUNCTION camel_store_subscribe_folder ##### -->
-<para>
-
-</para>
-
-@store: 
-@folder_name: 
-@cancellable: 
-@error: 
-@Returns: 
-
 <!-- ##### FUNCTION camel_store_sync ##### -->
 <para>
 
@@ -8217,17 +8119,6 @@ streams
 @error: 
 @Returns: 
 
-<!-- ##### FUNCTION camel_store_unsubscribe_folder ##### -->
-<para>
-
-</para>
-
-@store: 
-@folder_name: 
-@cancellable: 
-@error: 
-@Returns: 
-
 <!-- ##### FUNCTION camel_stream_filter_new_with_stream ##### -->
 <para>
 
@@ -8357,19 +8248,6 @@ streams
 
 @Returns: 
 
-<!-- ##### FUNCTION camel_transport_send_to ##### -->
-<para>
-
-</para>
-
-@transport: 
-@message: 
-@from: 
-@recipients: 
-@cancellable: 
-@error: 
-@Returns: 
-
 <!-- ##### MACRO camel_type_get_global_classfuncs ##### -->
 <para>