[evolution-data-server] CamelDataWrapper: Keep contents in a GByteArray.



commit 9804a01be7a9db5a30791ee3319a076e94946d72
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed Jul 6 14:58:51 2011 -0400

    CamelDataWrapper: Keep contents in a GByteArray.
    
    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                        |  112 ++++++++----
 camel/camel-data-wrapper.h                        |    9 +-
 camel/camel-multipart-signed.c                    |  201 +++++++++++----------
 camel/providers/imap/camel-imap-wrapper.c         |   39 +++--
 docs/reference/camel/camel-sections.txt           |    1 +
 docs/reference/camel/tmpl/camel-data-wrapper.sgml |    9 +
 6 files changed, 221 insertions(+), 150 deletions(-)
---
diff --git a/camel/camel-data-wrapper.c b/camel/camel-data-wrapper.c
index 59dc6fe..958117d 100644
--- a/camel/camel-data-wrapper.c
+++ b/camel/camel-data-wrapper.c
@@ -32,14 +32,19 @@
 #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
diff --git a/camel/camel-data-wrapper.h b/camel/camel-data-wrapper.h
index d363456..eb7e427 100644
--- a/camel/camel-data-wrapper.h
+++ b/camel/camel-data-wrapper.h
@@ -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);
diff --git a/camel/camel-multipart-signed.c b/camel/camel-multipart-signed.c
index ad86916..f0f28c4 100644
--- a/camel/camel-multipart-signed.c
+++ b/camel/camel-multipart-signed.c
@@ -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);
 
diff --git a/camel/providers/imap/camel-imap-wrapper.c b/camel/providers/imap/camel-imap-wrapper.c
index 6975e74..de2890e 100644
--- a/camel/providers/imap/camel-imap-wrapper.c
+++ b/camel/providers/imap/camel-imap-wrapper.c
@@ -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);
 	}
 
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index acea66f..8faf5ce 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -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
diff --git a/docs/reference/camel/tmpl/camel-data-wrapper.sgml b/docs/reference/camel/tmpl/camel-data-wrapper.sgml
index cb746fa..566a5e7 100644
--- a/docs/reference/camel/tmpl/camel-data-wrapper.sgml
+++ b/docs/reference/camel/tmpl/camel-data-wrapper.sgml
@@ -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>
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]