CamelDataWrapper: Keep contents in a GByteArray.
authorMatthew Barnes <mbarnes@redhat.com>
Wed, 6 Jul 2011 18:58:51 +0000 (14:58 -0400)
committerMatthew Barnes <mbarnes@redhat.com>
Wed, 6 Jul 2011 20:08:28 +0000 (16:08 -0400)
Keep CamelDataWrapper contents in an internal GByteArray rather than a
CamelStream.  The CamelStream was causing problems because it now needs
to be seekable, but in some cases we were getting a CamelStreamFilter
which is _not_ seekable.

Also add camel_data_wrapper_get_byte_array() for when you need direct
access to the contents.  This is sometimes more convenient than copying
it into a memory stream, but carries a thread-safety risk if you're not
careful.  Only CamelDataWrapper subclasses should really be using it.

This is another API and ABI break since CamelDataWrapper's CamelStream
pointer was a public struct member.

camel/camel-data-wrapper.c
camel/camel-data-wrapper.h
camel/camel-multipart-signed.c
camel/providers/imap/camel-imap-wrapper.c
docs/reference/camel/camel-sections.txt
docs/reference/camel/tmpl/camel-data-wrapper.sgml

index 59dc6fe..958117d 100644 (file)
 #include "camel-mime-filter-basic.h"
 #include "camel-mime-filter-crlf.h"
 #include "camel-stream-filter.h"
-#include "camel-stream.h"
+#include "camel-stream-mem.h"
 
 #define d(x)
 
+#define CAMEL_DATA_WRAPPER_GET_PRIVATE(obj) \
+       (G_TYPE_INSTANCE_GET_PRIVATE \
+       ((obj), CAMEL_TYPE_DATA_WRAPPER, CamelDataWrapperPrivate))
+
 typedef struct _AsyncContext AsyncContext;
 
 struct _CamelDataWrapperPrivate {
        GStaticMutex stream_lock;
+       GByteArray *byte_array;
 };
 
 struct _AsyncContext {
@@ -71,11 +76,6 @@ data_wrapper_dispose (GObject *object)
                data_wrapper->mime_type = NULL;
        }
 
-       if (data_wrapper->stream != NULL) {
-               g_object_unref (data_wrapper->stream);
-               data_wrapper->stream = NULL;
-       }
-
        /* Chain up to parent's dispose() method. */
        G_OBJECT_CLASS (camel_data_wrapper_parent_class)->dispose (object);
 }
@@ -83,9 +83,12 @@ data_wrapper_dispose (GObject *object)
 static void
 data_wrapper_finalize (GObject *object)
 {
-       CamelDataWrapper *data_wrapper = CAMEL_DATA_WRAPPER (object);
+       CamelDataWrapperPrivate *priv;
+
+       priv = CAMEL_DATA_WRAPPER_GET_PRIVATE (object);
 
-       g_static_mutex_free (&data_wrapper->priv->stream_lock);
+       g_static_mutex_free (&priv->stream_lock);
+       g_byte_array_free (priv->byte_array, TRUE);
 
        /* Chain up to parent's finalize() method. */
        G_OBJECT_CLASS (camel_data_wrapper_parent_class)->finalize (object);
@@ -135,16 +138,11 @@ data_wrapper_write_to_stream_sync (CamelDataWrapper *data_wrapper,
                                    GCancellable *cancellable,
                                    GError **error)
 {
+       CamelStream *memory_stream;
        gssize ret;
 
-       if (data_wrapper->stream == NULL) {
-               g_set_error (
-                       error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
-                       _("No stream available"));
-               return -1;
-       }
-
-       camel_data_wrapper_lock (data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK);
+       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)) {
@@ -153,24 +151,20 @@ data_wrapper_write_to_stream_sync (CamelDataWrapper *data_wrapper,
                return -1;
        }
 
-       if (G_IS_SEEKABLE (data_wrapper->stream)) {
-               gboolean success;
-
-               success = g_seekable_seek (
-                       G_SEEKABLE (data_wrapper->stream),
-                       0, G_SEEK_SET, cancellable, error);
+       memory_stream = camel_stream_mem_new ();
 
-               if (!success) {
-                       camel_data_wrapper_unlock (
-                               data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK);
-                       return -1;
-               }
-       }
+       /* We retain ownership of the byte array. */
+       camel_stream_mem_set_byte_array (
+               CAMEL_STREAM_MEM (memory_stream),
+               data_wrapper->priv->byte_array);
 
        ret = camel_stream_write_to_stream (
-               data_wrapper->stream, stream, cancellable, error);
+               memory_stream, stream, cancellable, error);
+
+       g_object_unref (memory_stream);
 
-       camel_data_wrapper_unlock (data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK);
+       camel_data_wrapper_unlock (
+               data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK);
 
        return ret;
 }
@@ -229,12 +223,37 @@ data_wrapper_construct_from_stream_sync (CamelDataWrapper *data_wrapper,
                                          GCancellable *cancellable,
                                          GError **error)
 {
-       if (data_wrapper->stream)
-               g_object_unref (data_wrapper->stream);
+       CamelStream *memory_stream;
+       gssize bytes_written;
 
-       data_wrapper->stream = g_object_ref (stream);
+       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 FALSE;
+       }
 
-       return TRUE;
+       /* Wipe any previous contents from our byte array. */
+       g_byte_array_set_size (data_wrapper->priv->byte_array, 0);
+
+       memory_stream = camel_stream_mem_new ();
+
+       /* We retain ownership of the byte array. */
+       camel_stream_mem_set_byte_array (
+               CAMEL_STREAM_MEM (memory_stream),
+               data_wrapper->priv->byte_array);
+
+       /* Transfer incoming contents to our byte array. */
+       bytes_written = camel_stream_write_to_stream (
+               stream, memory_stream, cancellable, error);
+
+       camel_data_wrapper_unlock (
+               data_wrapper, CAMEL_DATA_WRAPPER_STREAM_LOCK);
+
+       return (bytes_written >= 0);
 }
 
 static void
@@ -479,11 +498,10 @@ camel_data_wrapper_class_init (CamelDataWrapperClass *class)
 static void
 camel_data_wrapper_init (CamelDataWrapper *data_wrapper)
 {
-       data_wrapper->priv = G_TYPE_INSTANCE_GET_PRIVATE (
-               data_wrapper, CAMEL_TYPE_DATA_WRAPPER,
-               CamelDataWrapperPrivate);
+       data_wrapper->priv = CAMEL_DATA_WRAPPER_GET_PRIVATE (data_wrapper);
 
        g_static_mutex_init (&data_wrapper->priv->stream_lock);
+       data_wrapper->priv->byte_array = g_byte_array_new ();
 
        data_wrapper->mime_type = camel_content_type_new (
                "application", "octet-stream");
@@ -505,6 +523,26 @@ camel_data_wrapper_new (void)
 }
 
 /**
+ * camel_data_wrapper_get_byte_array:
+ * @data_wrapper: a #CamelDataWrapper
+ *
+ * Returns the #GByteArray being used to hold the contents of @data_wrapper.
+ *
+ * Note, it's up to the caller to use this in a thread-safe manner.
+ *
+ * Returns: the #GByteArray for @data_wrapper
+ *
+ * Since: 3.2
+ **/
+GByteArray *
+camel_data_wrapper_get_byte_array (CamelDataWrapper *data_wrapper)
+{
+       g_return_val_if_fail (CAMEL_IS_DATA_WRAPPER (data_wrapper), NULL);
+
+       return data_wrapper->priv->byte_array;
+}
+
+/**
  * camel_data_wrapper_set_mime_type:
  * @data_wrapper: a #CamelDataWrapper
  * @mime_type: a MIME type
index d363456..eb7e427 100644 (file)
@@ -75,7 +75,6 @@ struct _CamelDataWrapper {
        CamelTransferEncoding encoding;
 
        CamelContentType *mime_type;
-       CamelStream *stream;
 
        guint offline:1;
 };
@@ -145,9 +144,13 @@ struct _CamelDataWrapperClass {
 GType          camel_data_wrapper_get_type     (void);
 CamelDataWrapper *
                camel_data_wrapper_new          (void);
-void           camel_data_wrapper_set_mime_type (CamelDataWrapper *data_wrapper,
+GByteArray *   camel_data_wrapper_get_byte_array
+                                               (CamelDataWrapper *data_wrapper);
+void           camel_data_wrapper_set_mime_type
+                                               (CamelDataWrapper *data_wrapper,
                                                 const gchar *mime_type);
-gchar *                camel_data_wrapper_get_mime_type (CamelDataWrapper *data_wrapper);
+gchar *                camel_data_wrapper_get_mime_type
+                                               (CamelDataWrapper *data_wrapper);
 CamelContentType *
                camel_data_wrapper_get_mime_type_field
                                                (CamelDataWrapper *data_wrapper);
index ad86916..f0f28c4 100644 (file)
@@ -48,42 +48,28 @@ G_DEFINE_TYPE (CamelMultipartSigned, camel_multipart_signed, CAMEL_TYPE_MULTIPAR
 static CamelStream *
 multipart_signed_clip_stream (CamelMultipartSigned *mps,
                               goffset start,
-                              goffset end,
-                              GCancellable *cancellable,
-                              GError **error)
+                              goffset end)
 {
        CamelDataWrapper *data_wrapper;
-       CamelStream *stream;
-       gchar *buffer;
-       gssize n_read;
-       gsize length;
+       GByteArray *src;
+       GByteArray *dst;
 
        g_return_val_if_fail (start != -1, NULL);
        g_return_val_if_fail (end != -1, NULL);
        g_return_val_if_fail (end >= start, NULL);
 
        data_wrapper = CAMEL_DATA_WRAPPER (mps);
-       stream = data_wrapper->stream;
-
-       if (!g_seekable_seek (
-               G_SEEKABLE (stream), start,
-               G_SEEK_SET, cancellable, error))
-               return NULL;
-
-       length = end - start;
-       buffer = g_malloc0 (length + 1);
-
-       n_read = camel_stream_read (
-               stream, buffer, length, cancellable, error);
 
-       if (n_read >= 0)
-               stream = camel_stream_mem_new_with_buffer (buffer, n_read);
-       else
-               stream = NULL;
+       src = camel_data_wrapper_get_byte_array (data_wrapper);
+       dst = g_byte_array_new ();
 
-       g_free (buffer);
+       if (start + end <= src->len) {
+               const guint8 *data = &src->data[start];
+               g_byte_array_append (dst, data, end - start);
+       }
 
-       return stream;
+       /* Stream takes ownership of the byte array. */
+       return camel_stream_mem_new_with_byte_array (dst);
 }
 
 static gint
@@ -135,6 +121,8 @@ multipart_signed_parse_content (CamelMultipartSigned *mps)
 {
        CamelMimeParser *cmp;
        CamelMultipart *mp = (CamelMultipart *) mps;
+       CamelDataWrapper *data_wrapper;
+       GByteArray *byte_array;
        CamelStream *stream;
        const gchar *boundary;
        gchar *buf;
@@ -144,16 +132,19 @@ multipart_signed_parse_content (CamelMultipartSigned *mps)
        boundary = camel_multipart_get_boundary (mp);
        g_return_val_if_fail (boundary != NULL, -1);
 
-       stream = ((CamelDataWrapper *) mps)->stream;
-       g_return_val_if_fail (stream != NULL, -1);
+       data_wrapper = CAMEL_DATA_WRAPPER (mps);
+       byte_array = camel_data_wrapper_get_byte_array (data_wrapper);
+
+       stream = camel_stream_mem_new ();
+
+       /* Do not give the stream ownership of the byte array. */
+       camel_stream_mem_set_byte_array (
+               CAMEL_STREAM_MEM (stream), byte_array);
 
        /* This is all seriously complex.
           This is so we can parse all cases properly, without altering the content.
           All we are doing is finding part offsets. */
 
-       /* XXX Assumes data wrapper streams are always seekable. */
-       g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, NULL);
-
        cmp = camel_mime_parser_new ();
        camel_mime_parser_init_with_stream (cmp, stream, NULL);
        camel_mime_parser_push_state (cmp, CAMEL_MIME_PARSER_STATE_MULTIPART, boundary);
@@ -167,15 +158,11 @@ multipart_signed_parse_content (CamelMultipartSigned *mps)
                if (mps->start1 == -1) {
                        mps->start1 = camel_mime_parser_tell_start_headers (cmp);
                } else if (mps->start2 == -1) {
-                       GByteArray *buffer;
-
-                       buffer = camel_stream_mem_get_byte_array (
-                               CAMEL_STREAM_MEM (stream));
                        mps->start2 = camel_mime_parser_tell_start_headers (cmp);
                        mps->end1 = camel_mime_parser_tell_start_boundary (cmp);
-                       if (mps->end1 > mps->start1 && buffer->data[mps->end1-1] == '\n')
+                       if (mps->end1 > mps->start1 && byte_array->data[mps->end1-1] == '\n')
                                mps->end1--;
-                       if (mps->end1 > mps->start1 && buffer->data[mps->end1-1] == '\r')
+                       if (mps->end1 > mps->start1 && byte_array->data[mps->end1-1] == '\r')
                                mps->end1--;
                } else {
                        g_warning("multipart/signed has more than 2 parts, remaining parts ignored");
@@ -194,6 +181,7 @@ multipart_signed_parse_content (CamelMultipartSigned *mps)
        }
 
        g_object_unref (cmp);
+       g_object_unref (stream);
 
        if (mps->end2 == -1 || mps->start2 == -1) {
                if (mps->end1 == -1)
@@ -206,31 +194,6 @@ multipart_signed_parse_content (CamelMultipartSigned *mps)
 }
 
 static void
-multipart_signed_set_stream (CamelMultipartSigned *mps,
-                             CamelStream *stream)
-{
-       CamelDataWrapper *dw = (CamelDataWrapper *) mps;
-
-       if (dw->stream)
-               g_object_unref (dw->stream);
-       dw->stream = stream;
-
-       mps->start1 = -1;
-       if (mps->content) {
-               g_object_unref (mps->content);
-               mps->content = NULL;
-       }
-       if (mps->contentraw) {
-               g_object_unref (mps->contentraw);
-               mps->contentraw = NULL;
-       }
-       if (mps->signature) {
-               g_object_unref (mps->signature);
-               mps->signature = NULL;
-       }
-}
-
-static void
 multipart_signed_dispose (GObject *object)
 {
        CamelMultipartSigned *multipart;
@@ -304,11 +267,14 @@ multipart_signed_write_to_stream_sync (CamelDataWrapper *data_wrapper,
 {
        CamelMultipartSigned *mps = (CamelMultipartSigned *) data_wrapper;
        CamelMultipart *mp = (CamelMultipart *) mps;
+       GByteArray *byte_array;
        const gchar *boundary;
        gssize total = 0;
        gssize count;
        gchar *content;
 
+       byte_array = camel_data_wrapper_get_byte_array (data_wrapper);
+
        /* we have 3 basic cases:
           1. constructed, we write out the data wrapper stream we got
           2. signed content, we create and write out a new stream
@@ -317,13 +283,10 @@ multipart_signed_write_to_stream_sync (CamelDataWrapper *data_wrapper,
 
        /* 1 */
        /* FIXME: locking? */
-       if (data_wrapper->stream) {
-               /* XXX Assumes data wrapper streams are always seekable. */
-               g_seekable_seek (
-                       G_SEEKABLE (data_wrapper->stream),
-                       0, G_SEEK_SET, NULL, NULL);
-               return camel_stream_write_to_stream (
-                       data_wrapper->stream, stream, cancellable, error);
+       if (byte_array->len > 0) {
+               return camel_stream_write (
+                       stream, (gchar *) byte_array->data,
+                       byte_array->len, cancellable, error);
        }
 
        /* 3 */
@@ -416,16 +379,35 @@ multipart_signed_construct_from_stream_sync (CamelDataWrapper *data_wrapper,
                                              GCancellable *cancellable,
                                              GError **error)
 {
-       CamelMultipartSigned *mps = (CamelMultipartSigned *) data_wrapper;
-       CamelStream *mem = camel_stream_mem_new ();
-
-       if (camel_stream_write_to_stream (
-               stream, mem, cancellable, error) == -1)
-               return FALSE;
-
-       multipart_signed_set_stream (mps, mem);
+       CamelDataWrapperClass *parent_class;
+       CamelMultipartSigned *mps;
+       gboolean success;
+
+       mps = CAMEL_MULTIPART_SIGNED (data_wrapper);
+
+       /* Chain up to parent's construct_from_stream_sync() method. */
+       parent_class = CAMEL_DATA_WRAPPER_CLASS (
+               camel_multipart_signed_parent_class);
+       success = parent_class->construct_from_stream_sync (
+               data_wrapper, stream, cancellable, error);
+
+       if (success) {
+               mps->start1 = -1;
+               if (mps->content != NULL) {
+                       g_object_unref (mps->content);
+                       mps->content = NULL;
+               }
+               if (mps->contentraw != NULL) {
+                       g_object_unref (mps->contentraw);
+                       mps->contentraw = NULL;
+               }
+               if (mps->signature != NULL) {
+                       g_object_unref (mps->signature);
+                       mps->signature = NULL;
+               }
+       }
 
-       return TRUE;
+       return success;
 }
 
 static void
@@ -464,30 +446,36 @@ multipart_signed_get_part (CamelMultipart *multipart,
                            guint index)
 {
        CamelMultipartSigned *mps = (CamelMultipartSigned *) multipart;
-       CamelDataWrapper *dw = (CamelDataWrapper *) multipart;
+       CamelDataWrapper *data_wrapper;
        CamelStream *stream;
+       GByteArray *byte_array;
+
+       data_wrapper = CAMEL_DATA_WRAPPER (multipart);
+       byte_array = camel_data_wrapper_get_byte_array (data_wrapper);
 
        switch (index) {
        case CAMEL_MULTIPART_SIGNED_CONTENT:
                if (mps->content)
                        return mps->content;
                if (mps->contentraw) {
+                       g_return_val_if_fail (
+                               G_IS_SEEKABLE (mps->contentraw), NULL);
                        stream = g_object_ref (mps->contentraw);
                } else if (mps->start1 == -1
                           && multipart_signed_parse_content (mps) == -1
-                          && ((CamelDataWrapper *) mps)->stream == NULL) {
+                          && byte_array->len == 0) {
                        g_warning("Trying to get content on an invalid multipart/signed");
                        return NULL;
-               } else if (dw->stream == NULL) {
+               } else if (byte_array->len == 0) {
                        return NULL;
                } else if (mps->start1 == -1) {
-                       stream = g_object_ref (dw->stream);
+                       stream = camel_stream_mem_new ();
+                       camel_stream_mem_set_byte_array (
+                               CAMEL_STREAM_MEM (stream), byte_array);
                } else {
                        stream = multipart_signed_clip_stream (
-                               mps, mps->start1, mps->end1, NULL, NULL);
+                               mps, mps->start1, mps->end1);
                }
-               /* XXX The "contentraw" stream is safe to assume to
-                *     be seekable.  Data wrapper streams less so. */
                g_seekable_seek (
                        G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, NULL);
                mps->content = camel_mime_part_new ();
@@ -502,12 +490,11 @@ multipart_signed_get_part (CamelMultipart *multipart,
                    && multipart_signed_parse_content (mps) == -1) {
                        g_warning("Trying to get signature on invalid multipart/signed");
                        return NULL;
-               } else if (dw->stream == NULL) {
+               } else if (byte_array->len == 0) {
                        return NULL;
                }
                stream = multipart_signed_clip_stream (
-                       mps, mps->start2, mps->end2, NULL, NULL);
-               /* XXX Assumes data wrapper streams are always seekable. */
+                       mps, mps->start2, mps->end2);
                g_seekable_seek (
                        G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, NULL);
                mps->signature = camel_mime_part_new ();
@@ -526,8 +513,12 @@ multipart_signed_get_part (CamelMultipart *multipart,
 static guint
 multipart_signed_get_number (CamelMultipart *multipart)
 {
-       CamelDataWrapper *dw = (CamelDataWrapper *) multipart;
        CamelMultipartSigned *mps = (CamelMultipartSigned *) multipart;
+       CamelDataWrapper *data_wrapper;
+       GByteArray *byte_array;
+
+       data_wrapper = CAMEL_DATA_WRAPPER (multipart);
+       byte_array = camel_data_wrapper_get_byte_array (data_wrapper);
 
        /* check what we have, so we return something reasonable */
 
@@ -535,7 +526,7 @@ multipart_signed_get_number (CamelMultipart *multipart)
                return 2;
 
        if (mps->start1 == -1 && multipart_signed_parse_content (mps) == -1) {
-               if (dw->stream == NULL)
+               if (byte_array->len == 0)
                        return 0;
                else
                        return 1;
@@ -551,9 +542,10 @@ multipart_signed_construct_from_parser (CamelMultipart *multipart,
        gint err;
        CamelContentType *content_type;
        CamelMultipartSigned *mps = (CamelMultipartSigned *) multipart;
+       CamelDataWrapper *data_wrapper;
+       GByteArray *byte_array;
        gchar *buf;
        gsize len;
-       CamelStream *stream;
 
        /* we *must not* be in multipart state, otherwise the mime parser will
           parse the headers which is a no no @#$@# stupid multipart/signed spec */
@@ -563,11 +555,28 @@ multipart_signed_construct_from_parser (CamelMultipart *multipart,
        content_type = camel_mime_parser_content_type (mp);
        camel_multipart_set_boundary(multipart, camel_content_type_param(content_type, "boundary"));
 
-       stream = camel_stream_mem_new ();
+       data_wrapper = CAMEL_DATA_WRAPPER (multipart);
+       byte_array = camel_data_wrapper_get_byte_array (data_wrapper);
+
+       /* Wipe any previous contents from the byte array. */
+       g_byte_array_set_size (byte_array, 0);
+
        while (camel_mime_parser_step (mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_BODY_END)
-               camel_stream_write (stream, buf, len, NULL, NULL);
+               g_byte_array_append (byte_array, (guint8 *) buf, len);
 
-       multipart_signed_set_stream (mps, stream);
+       mps->start1 = -1;
+       if (mps->content) {
+               g_object_unref (mps->content);
+               mps->content = NULL;
+       }
+       if (mps->contentraw) {
+               g_object_unref (mps->contentraw);
+               mps->contentraw = NULL;
+       }
+       if (mps->signature) {
+               g_object_unref (mps->signature);
+               mps->signature = NULL;
+       }
 
        err = camel_mime_parser_errno (mp);
        if (err != 0) {
@@ -682,12 +691,8 @@ camel_multipart_signed_get_content_stream (CamelMultipartSigned *mps,
 
                /* first, prepare our parts */
 
-               /* FIXME Missing a GCancellable */
                base_stream = multipart_signed_clip_stream (
-                       mps, mps->start1, mps->end1, NULL, error);
-
-               if (base_stream == NULL)
-                       return NULL;
+                       mps, mps->start1, mps->end1);
 
                filter_stream = camel_stream_filter_new (base_stream);
 
index 6975e74..de2890e 100644 (file)
@@ -40,21 +40,30 @@ struct _CamelImapWrapperPrivate {
 
 G_DEFINE_TYPE (CamelImapWrapper, camel_imap_wrapper, CAMEL_TYPE_DATA_WRAPPER)
 
-static void
+static gboolean
 imap_wrapper_hydrate (CamelImapWrapper *imap_wrapper,
-                      CamelStream *stream)
+                      CamelStream *stream,
+                      GCancellable *cancellable,
+                      GError **error)
 {
        CamelDataWrapper *data_wrapper = (CamelDataWrapper *) imap_wrapper;
+       gboolean success;
 
-       data_wrapper->stream = g_object_ref (stream);
-       data_wrapper->offline = FALSE;
+       success = camel_data_wrapper_construct_from_stream_sync (
+               data_wrapper, stream, cancellable, error);
 
-       g_object_unref (imap_wrapper->folder);
-       imap_wrapper->folder = NULL;
-       g_free (imap_wrapper->uid);
-       imap_wrapper->uid = NULL;
-       g_free (imap_wrapper->part_spec);
-       imap_wrapper->part_spec = NULL;
+       if (success) {
+               data_wrapper->offline = FALSE;
+
+               g_object_unref (imap_wrapper->folder);
+               imap_wrapper->folder = NULL;
+               g_free (imap_wrapper->uid);
+               imap_wrapper->uid = NULL;
+               g_free (imap_wrapper->part_spec);
+               imap_wrapper->part_spec = NULL;
+       }
+
+       return success;
 }
 
 static void
@@ -92,6 +101,7 @@ imap_wrapper_write_to_stream_sync (CamelDataWrapper *data_wrapper,
                                    GError **error)
 {
        CamelImapWrapper *imap_wrapper = CAMEL_IMAP_WRAPPER (data_wrapper);
+       gboolean success = TRUE;
 
        CAMEL_IMAP_WRAPPER_LOCK (imap_wrapper, lock);
        if (data_wrapper->offline) {
@@ -106,11 +116,16 @@ imap_wrapper_write_to_stream_sync (CamelDataWrapper *data_wrapper,
                        return -1;
                }
 
-               imap_wrapper_hydrate (imap_wrapper, datastream);
+               success = imap_wrapper_hydrate (
+                       imap_wrapper, datastream, cancellable, error);
+
                g_object_unref (datastream);
        }
        CAMEL_IMAP_WRAPPER_UNLOCK (imap_wrapper, lock);
 
+       if (!success)
+               return -1;
+
        return CAMEL_DATA_WRAPPER_CLASS (camel_imap_wrapper_parent_class)->
                write_to_stream_sync (data_wrapper, stream, cancellable, error);
 }
@@ -176,7 +191,7 @@ camel_imap_wrapper_new (CamelImapFolder *imap_folder,
                        !sync_offline, NULL, NULL);
 
        if (stream) {
-               imap_wrapper_hydrate (imap_wrapper, stream);
+               imap_wrapper_hydrate (imap_wrapper, stream, NULL, NULL);
                g_object_unref (stream);
        }
 
index acea66f..8faf5ce 100644 (file)
@@ -217,6 +217,7 @@ camel_data_cache_get_type
 <TITLE>CamelDataWrapper</TITLE>
 CamelDataWrapper
 camel_data_wrapper_new
+camel_data_wrapper_get_byte_array
 camel_data_wrapper_set_mime_type
 camel_data_wrapper_get_mime_type
 camel_data_wrapper_get_mime_type_field
index cb746fa..566a5e7 100644 (file)
@@ -35,6 +35,15 @@ CamelDataWrapper
 @Returns: 
 
 
+<!-- ##### FUNCTION camel_data_wrapper_get_byte_array ##### -->
+<para>
+
+</para>
+
+@data_wrapper: 
+@Returns: 
+
+
 <!-- ##### FUNCTION camel_data_wrapper_set_mime_type ##### -->
 <para>