[evolution-mapi] Cannot read/write large attachments



commit ec8c9ac9870dbf3007684155ebb50162fa8f4612
Author: Milan Crha <mcrha redhat com>
Date:   Thu Feb 2 15:44:22 2012 +0100

    Cannot read/write large attachments

 src/libexchangemapi/e-mapi-cal-utils.c     |   30 ++--
 src/libexchangemapi/e-mapi-connection.c    |  297 ++++++++++++++++++++++------
 src/libexchangemapi/e-mapi-connection.h    |   42 ++++-
 src/libexchangemapi/e-mapi-debug.c         |   52 +++++-
 src/libexchangemapi/e-mapi-fast-transfer.c |   56 +++++-
 src/libexchangemapi/e-mapi-mail-utils.c    |  120 +++++++-----
 6 files changed, 463 insertions(+), 134 deletions(-)
---
diff --git a/src/libexchangemapi/e-mapi-cal-utils.c b/src/libexchangemapi/e-mapi-cal-utils.c
index a2eb8f3..1344a51 100644
--- a/src/libexchangemapi/e-mapi-cal-utils.c
+++ b/src/libexchangemapi/e-mapi-cal-utils.c
@@ -792,14 +792,14 @@ set_attachments_to_comp (EMapiConnection *conn,
 	e_cal_component_get_uid (comp, &uid);
 
 	for (attach = attachments; attach; attach = attach->next) {
-		const struct SBinary_short *data_bin;
+		uint64_t data_cb = 0;
+		const uint8_t *data_lpb = NULL;
 		const gchar *filename;
 		const uint32_t *ui32;
 		gchar *path, *attach_uri;
 		GError *error = NULL;
 
-		data_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachDataBinary);
-		if (!data_bin) {
+		if (!e_mapi_attachment_get_bin_prop (attach, PidTagAttachDataBinary, &data_cb, &data_lpb)) {
 			g_debug ("%s: Skipping calendar attachment without data", G_STRFUNC);
 			continue;
 		}
@@ -819,7 +819,7 @@ set_attachments_to_comp (EMapiConnection *conn,
 			continue;
 		}
 
-		if (!g_file_set_contents (path, (const gchar *) data_bin->lpb, data_bin->cb, &error)) {
+		if (!g_file_set_contents (path, (const gchar *) data_lpb, data_cb, &error)) {
 			g_debug ("%s: Failed to write attachment content to '%s': %s", G_STRFUNC, path, error ? error->message : "Unknown error");
 			g_free (attach_uri);
 			g_clear_error (&error);
@@ -900,12 +900,13 @@ e_mapi_cal_util_object_to_comp (EMapiConnection *conn,
 
 		g_free (utf8_str);
 	} else {
-		const struct SBinary_short *html_bin = e_mapi_util_find_array_propval (&object->properties, PidTagHtml);
+		uint64_t html_cb = 0;
+		const uint8_t *html_lpb = NULL;
 
-		if (html_bin) {
+		if (e_mapi_object_get_bin_prop (object, PidTagHtml, &html_cb, &html_lpb)) {
 			gchar *utf8_str = NULL;
 
-			if (e_mapi_utils_ensure_utf8_string (PidTagHtml, ui32, html_bin->lpb, html_bin->cb, &utf8_str))
+			if (e_mapi_utils_ensure_utf8_string (PidTagHtml, ui32, html_lpb, html_cb, &utf8_str))
 				icalcomponent_set_description (ical_comp, utf8_str);
 
 			g_free (utf8_str);
@@ -1471,7 +1472,8 @@ e_mapi_cal_utils_add_attachments (EMapiObject *object,
 			guint filelength = g_mapped_file_get_length (mapped_file);
 			const gchar *split_name;
 			uint32_t ui32;
-			struct SBinary_short bin;
+			uint64_t data_cb;
+			uint8_t *data_lpb;
 
 			if (g_str_has_prefix (filename, safeuid)) {
 				split_name = (filename + strlen (safeuid) + strlen ("-"));
@@ -1504,9 +1506,9 @@ e_mapi_cal_utils_add_attachments (EMapiObject *object,
 			set_value (PidTagAttachFilename, split_name);
 			set_value (PidTagAttachLongFilename, split_name);
 
-			bin.cb = filelength;
-			bin.lpb = talloc_memdup (attachment, attach, bin.cb);
-			set_value (PidTagAttachDataBinary, &bin);
+			data_cb = filelength;
+			data_lpb = talloc_memdup (attachment, attach, data_cb);
+			e_mapi_attachment_add_streamed (attachment, PidTagAttachDataBinary, data_cb, data_lpb);
 
 			#undef set_value
 
@@ -2080,10 +2082,10 @@ e_mapi_cal_utils_comp_to_object (EMapiConnection *conn,
 		set_value (PidLidIsRecurring, &b);
 
 		if (b) {
-			struct SBinary_short bin;
+			struct SBinary_short recur_bin;
 
-			if (e_mapi_cal_util_rrule_to_bin (comp, &bin, object)) {
-				set_value (PidLidAppointmentRecur, &bin);
+			if (e_mapi_cal_util_rrule_to_bin (comp, &recur_bin, object)) {
+				set_value (PidLidAppointmentRecur, &recur_bin);
 			}
 		}
 
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index 6311b19..32ddd16 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -2296,7 +2296,8 @@ fetch_object_property_as_stream (EMapiConnection *conn,
 				 TALLOC_CTX *mem_ctx,
 				 mapi_object_t *obj_message,
 				 uint32_t proptag,
-				 struct SBinary_short *bin,
+				 uint64_t *pcb,
+				 uint8_t **plpb,
 				 GCancellable *cancellable,
 				 GError **perror)
 {
@@ -2304,12 +2305,15 @@ fetch_object_property_as_stream (EMapiConnection *conn,
 	mapi_object_t obj_stream;
 	uint32_t buf_size, max_read;
 	uint16_t off_data, cn_read;
+	uint64_t cb = 0;
+	uint8_t *lpb = NULL;
 	gboolean done = FALSE;
 
 	g_return_val_if_fail (conn != NULL, MAPI_E_INVALID_PARAMETER);
 	g_return_val_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER);
 	g_return_val_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER);
-	g_return_val_if_fail (bin != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (pcb != NULL, MAPI_E_INVALID_PARAMETER);
+	g_return_val_if_fail (plpb != NULL, MAPI_E_INVALID_PARAMETER);
 
 	mapi_object_init (&obj_stream);
 
@@ -2319,7 +2323,7 @@ fetch_object_property_as_stream (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	bin->cb = 0;
+	cb = 0;
 
 	ms = GetStreamSize (&obj_stream, &buf_size);
 	if (ms != MAPI_E_SUCCESS) {
@@ -2327,16 +2331,16 @@ fetch_object_property_as_stream (EMapiConnection *conn,
 		goto cleanup;
 	}
 
-	bin->cb = buf_size;
-	bin->lpb = talloc_size (mem_ctx, bin->cb + 1);
-	if (!bin->lpb || !bin->cb)
+	cb = buf_size;
+	lpb = talloc_size (mem_ctx, cb + 1);
+	if (!lpb || !cb)
 		goto cleanup;
 
 	/* determine max_read first, to read by chunks as long as possible */
 	off_data = 0;
 	max_read = buf_size > STREAM_MAX_READ_SIZE ? STREAM_MAX_READ_SIZE : buf_size;
 	do {
-		ms = ReadStream (&obj_stream, (bin->lpb) + off_data, max_read, &cn_read);
+		ms = ReadStream (&obj_stream, lpb + off_data, max_read, &cn_read);
 		if (ms == MAPI_E_SUCCESS) {
 			if (cn_read == 0) {
 				done = TRUE;
@@ -2358,7 +2362,7 @@ fetch_object_property_as_stream (EMapiConnection *conn,
 	} while (ms == 0x2c80); /* an error when max_read is too large? */
 
 	while (!done) {
-		ms = ReadStream (&obj_stream, bin->lpb + off_data, max_read, &cn_read);
+		ms = ReadStream (&obj_stream, lpb + off_data, max_read, &cn_read);
 		if (ms != MAPI_E_SUCCESS) {
 			make_mapi_error (perror, "ReadStream", ms);
 			done = TRUE;
@@ -2374,6 +2378,9 @@ fetch_object_property_as_stream (EMapiConnection *conn,
  cleanup:
 	mapi_object_release (&obj_stream);
 
+	*pcb = cb;
+	*plpb = lpb;
+
 	return ms;
 }
 
@@ -2439,22 +2446,16 @@ fetch_object_attachment_cb (EMapiConnection *conn,
 	attach_method = e_mapi_util_find_row_propval (srow, PidTagAttachMethod);
 	if (attach_method && *attach_method == ATTACH_BY_VALUE) {
 		if (!e_mapi_util_find_array_propval (&attachment->properties, PidTagAttachDataBinary)) {
-			struct SBinary_short bin;
+			uint64_t cb = 0;
+			uint8_t *lpb = NULL;
 
-			ms = fetch_object_property_as_stream (conn, mem_ctx, &obj_attach, PidTagAttachDataBinary, &bin, cancellable, perror);
+			ms = fetch_object_property_as_stream (conn, mem_ctx, &obj_attach, PidTagAttachDataBinary, &cb, &lpb, cancellable, perror);
 			if (ms != MAPI_E_SUCCESS) {
 				make_mapi_error (perror, "Attachment::fetch PidTagAttachDataBinary", ms);
 				goto cleanup;
 			}
 
-			attachment->properties.cValues++;
-			attachment->properties.lpProps = talloc_realloc (mem_ctx,
-									 attachment->properties.lpProps,
-									 struct mapi_SPropValue,
-									 attachment->properties.cValues + 1);
-			attachment->properties.lpProps[attachment->properties.cValues - 1].ulPropTag = PidTagAttachDataBinary;
-			attachment->properties.lpProps[attachment->properties.cValues - 1].value.bin = bin;
-			attachment->properties.lpProps[attachment->properties.cValues].ulPropTag = 0;
+			e_mapi_attachment_add_streamed (attachment, PidTagAttachDataBinary, cb, lpb);
 		}
 	} else if (attach_method && *attach_method == ATTACH_EMBEDDED_MSG) {
 		mapi_object_t obj_emb_msg;
@@ -2568,39 +2569,34 @@ e_mapi_connection_fetch_object_internal (EMapiConnection *conn,
 		uint8_t best_body = 0;
 
 		if (GetBestBody (obj_message, &best_body) == MAPI_E_SUCCESS && best_body == olEditorHTML) {
-			struct SBinary_short bin;
+			uint64_t cb = 0;
+			uint8_t *lpb = NULL;
 
-			ms = fetch_object_property_as_stream (conn, mem_ctx, obj_message, PidTagHtml, &bin, cancellable, perror);
+			ms = fetch_object_property_as_stream (conn, mem_ctx, obj_message, PidTagHtml, &cb, &lpb, cancellable, perror);
 			if (ms != MAPI_E_SUCCESS) {
 				make_mapi_error (perror, "Object::fetch PidTagHtml", ms);
 				goto cleanup;
 			}
 
-			object->properties.cValues++;
-			object->properties.lpProps = talloc_realloc (mem_ctx,
-								     object->properties.lpProps,
-								     struct mapi_SPropValue,
-								     object->properties.cValues + 1);
-			object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidTagHtml;
-			object->properties.lpProps[object->properties.cValues - 1].value.bin = bin;
-			object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
+			e_mapi_object_add_streamed (object, PidTagHtml, cb, lpb);
 		}
 	}
 
 	if (!e_mapi_util_find_array_propval (&object->properties, PidTagBody)) {
-		struct SBinary_short bin;
+		uint64_t cb = 0;
+		uint8_t *lpb = NULL;
 
-		if (fetch_object_property_as_stream (conn, mem_ctx, obj_message, PidTagBody, &bin, cancellable, NULL) == MAPI_E_SUCCESS) {
+		if (fetch_object_property_as_stream (conn, mem_ctx, obj_message, PidTagBody, &cb, &lpb, cancellable, NULL) == MAPI_E_SUCCESS) {
 			object->properties.cValues++;
 			object->properties.lpProps = talloc_realloc (mem_ctx,
 								     object->properties.lpProps,
 								     struct mapi_SPropValue,
 								     object->properties.cValues + 1);
 			object->properties.lpProps[object->properties.cValues - 1].ulPropTag = PidTagBody;
-			if (bin.cb > 0 && bin.lpb[bin.cb - 1] == 0)
-				object->properties.lpProps[object->properties.cValues - 1].value.lpszW = (const char *) talloc_steal (object, bin.lpb);
+			if (cb > 0 && lpb[cb - 1] == 0)
+				object->properties.lpProps[object->properties.cValues - 1].value.lpszW = (const char *) talloc_steal (object, lpb);
 			else
-				object->properties.lpProps[object->properties.cValues - 1].value.lpszW = talloc_strndup (object, (char *) bin.lpb, bin.cb);
+				object->properties.lpProps[object->properties.cValues - 1].value.lpszW = talloc_strndup (object, (char *) lpb, cb);
 			object->properties.lpProps[object->properties.cValues].ulPropTag = 0;
 		}
 	}
@@ -3048,16 +3044,12 @@ e_mapi_connection_transfer_summary (EMapiConnection *conn,
 	return ms == MAPI_E_SUCCESS;
 }
 
-typedef struct {
-	uint32_t proptag;
-	uint32_t cb;
-	const uint8_t *lpb; /* taken from the original mapi prop, no need to copy the memory */
-} EMapiStreamedProp;
-
 static gboolean
 convert_mapi_props_to_props (EMapiConnection *conn,
 			     mapi_object_t *obj_folder,
 			     const struct mapi_SPropValue_array *mapi_props,
+			     const EMapiStreamedProp *known_streams,
+			     guint known_streams_count,
 			     struct SPropValue **props,
 			     uint32_t *propslen,
 			     EMapiStreamedProp **streams, /* can be NULL for no streaming */
@@ -3078,8 +3070,24 @@ convert_mapi_props_to_props (EMapiConnection *conn,
 	e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 	if (streams) {
 		e_return_val_mapi_error_if_fail (streamslen != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+	} else {
+		e_return_val_mapi_error_if_fail (known_streams == NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 	}
 
+	#define addstream() {										\
+			if (!*streams) {								\
+				*streams = g_new0 (EMapiStreamedProp, 1);				\
+				*streamslen = 0;							\
+			} else {									\
+				*streams = g_renew (EMapiStreamedProp, *streams, *streamslen + 1);	\
+			}										\
+													\
+			(*streams)[*streamslen].proptag = proptag;					\
+			(*streams)[*streamslen].cb = 0;							\
+			(*streams)[*streamslen].lpb = NULL;						\
+			(*streamslen) += 1;								\
+		}
+
 	for (ii = 0; ii < mapi_props->cValues; ii++) {
 		gboolean processed = FALSE;
 		uint32_t proptag = mapi_props->lpProps[ii].ulPropTag;
@@ -3097,20 +3105,6 @@ convert_mapi_props_to_props (EMapiConnection *conn,
 			const gchar *str;
 			const struct SBinary_short *bin;
 
-			#define addstream() {										\
-					if (!*streams) {								\
-						*streams = g_new0 (EMapiStreamedProp, 1);				\
-						*streamslen = 0;							\
-					} else {									\
-						*streams = g_renew (EMapiStreamedProp, *streams, *streamslen + 1);	\
-					}										\
-															\
-					(*streams)[*streamslen].proptag = proptag;					\
-					(*streams)[*streamslen].cb = 0;							\
-					(*streams)[*streamslen].lpb = NULL;						\
-					(*streamslen) += 1;								\
-				}
-
 			switch (proptag & 0xFFFF) {
 			case PT_BINARY:
 				bin = propdata;
@@ -3160,14 +3154,25 @@ convert_mapi_props_to_props (EMapiConnection *conn,
 				}
 				break;
 			}
-
-			#undef addstream
 		}
 
 		if (!processed)
 			e_mapi_utils_add_spropvalue (mem_ctx, props, propslen, proptag, propdata);
 	}
 
+	if (known_streams && known_streams_count > 0 && streams) {
+		for (ii = 0; ii < known_streams_count; ii++) {
+			uint32_t proptag = known_streams[ii].proptag;
+
+			maybe_add_named_id_tag (proptag, &named_ids_list, &named_ids_len);
+
+			addstream ();
+			(*streams)[(*streamslen) - 1].cb = known_streams[ii].cb;
+			(*streams)[(*streamslen) - 1].lpb = known_streams[ii].lpb;
+		}
+	}
+	#undef addstream
+
 	if (named_ids_list) {
 		GHashTable *replace_hash = NULL;
 
@@ -3209,7 +3214,7 @@ write_streamed_prop (EMapiConnection *conn,
 		     GError **perror)
 {
 	enum MAPISTATUS	ms;
-	uint32_t total_written;
+	uint64_t total_written;
 	gboolean done = FALSE;
 	mapi_object_t obj_stream;
 
@@ -3291,6 +3296,8 @@ update_props_on_object (EMapiConnection *conn,
 			mapi_object_t *obj_folder,
 			mapi_object_t *obj_object,
 			const struct mapi_SPropValue_array *properties,
+			const EMapiStreamedProp *known_streams,
+			guint known_streams_count,
 			TALLOC_CTX *mem_ctx,
 			GCancellable *cancellable,
 			GError **perror)
@@ -3306,7 +3313,7 @@ update_props_on_object (EMapiConnection *conn,
 
 	LOCK ();
 
-	if (!convert_mapi_props_to_props (conn, obj_folder, properties, &props, &propslen, &streams, &streamslen, mem_ctx, cancellable, perror)) {
+	if (!convert_mapi_props_to_props (conn, obj_folder, properties, known_streams, known_streams_count, &props, &propslen, &streams, &streamslen, mem_ctx, cancellable, perror)) {
 		ms = MAPI_E_CALL_FAILED;
 		make_mapi_error (perror, "convert_mapi_props_to_props", ms);
 		goto cleanup;
@@ -3373,7 +3380,7 @@ update_recipient_properties (EMapiConnection *conn,
 
 	g_return_val_if_fail (recipient != NULL, FALSE);
 
-	if (!convert_mapi_props_to_props (conn, obj_folder, &recipient->properties, &props, &propslen, NULL, NULL, mem_ctx, cancellable, perror))
+	if (!convert_mapi_props_to_props (conn, obj_folder, &recipient->properties, NULL, 0, &props, &propslen, NULL, NULL, mem_ctx, cancellable, perror))
 		return FALSE;
 
 	for (ii = 0; ii < propslen; ii++) {
@@ -3703,7 +3710,10 @@ add_object_attachments (EMapiConnection *conn,
 			goto cleanup;
 		}
 
-		if (!update_props_on_object (conn, obj_folder, &obj_attach, &attachment->properties, mem_ctx, cancellable, perror)) {
+		if (!update_props_on_object (conn, obj_folder, &obj_attach,
+			&attachment->properties,
+			attachment->streamed_properties, attachment->streamed_properties_count,
+			mem_ctx, cancellable, perror)) {
 			ms = MAPI_E_CALL_FAILED;
 			make_mapi_error (perror, "update_props_on_object", ms);
 			goto cleanup;
@@ -3767,7 +3777,10 @@ update_message_with_object (EMapiConnection *conn,
 	e_return_val_mapi_error_if_fail (obj_message != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 	e_return_val_mapi_error_if_fail (object != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-	if (!update_props_on_object (conn, obj_folder, obj_message, &object->properties, mem_ctx, cancellable, perror))
+	if (!update_props_on_object (conn, obj_folder, obj_message,
+		&object->properties,
+		object->streamed_properties, object->streamed_properties_count,
+		mem_ctx, cancellable, perror))
 		return FALSE;
 
 	if (g_cancellable_set_error_if_cancelled (cancellable, perror))
@@ -6824,6 +6837,8 @@ e_mapi_attachment_new (TALLOC_CTX *mem_ctx)
 
 	attachment->properties.cValues = 0;
 	attachment->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
+	attachment->streamed_properties = NULL;
+	attachment->streamed_properties_count = 0;
 	attachment->embedded_object = NULL;
 	attachment->next = NULL;
 
@@ -6840,9 +6855,89 @@ e_mapi_attachment_free (EMapiAttachment *attachment)
 
 	e_mapi_object_free (attachment->embedded_object);
 	talloc_free (attachment->properties.lpProps);
+	talloc_free (attachment->streamed_properties);
 	talloc_free (attachment);
 }
 
+void
+e_mapi_attachment_add_streamed (EMapiAttachment *attachment,
+				uint32_t proptag,
+				uint64_t cb,
+				const uint8_t *lpb)
+{
+	guint32 index;
+
+	g_return_if_fail (attachment != NULL);
+	g_return_if_fail (proptag != 0);
+	g_return_if_fail (e_mapi_attachment_get_streamed (attachment, proptag) == NULL);
+
+	attachment->streamed_properties = talloc_realloc (attachment,
+		attachment->streamed_properties,
+		EMapiStreamedProp,
+		attachment->streamed_properties_count + 1);
+	g_return_if_fail (attachment->streamed_properties != NULL);
+
+	index = attachment->streamed_properties_count;
+	attachment->streamed_properties_count++;
+	attachment->streamed_properties[index].proptag = proptag;
+	attachment->streamed_properties[index].cb = cb;
+	attachment->streamed_properties[index].lpb = lpb;
+}
+
+EMapiStreamedProp *
+e_mapi_attachment_get_streamed (EMapiAttachment *attachment,
+				uint32_t proptag)
+{
+	guint32 ii;
+
+	g_return_val_if_fail (attachment != NULL, NULL);
+
+	if (!attachment->streamed_properties_count || !attachment->streamed_properties)
+		return NULL;
+
+	for (ii = 0; ii < attachment->streamed_properties_count; ii++) {
+		if (attachment->streamed_properties[ii].proptag == proptag)
+			return &attachment->streamed_properties[ii];
+	}
+
+	return NULL;
+}
+
+gboolean
+e_mapi_attachment_get_bin_prop (EMapiAttachment *attachment,
+				uint32_t proptag,
+				uint64_t *cb,
+				const uint8_t **lpb)
+{
+	EMapiStreamedProp *streamed;
+	const struct SBinary_short *bin;
+
+	g_return_val_if_fail (attachment != NULL, FALSE);
+	g_return_val_if_fail (cb != NULL, FALSE);
+	g_return_val_if_fail (lpb != NULL, FALSE);
+
+	*cb = 0;
+	*lpb = NULL;
+
+	streamed = e_mapi_attachment_get_streamed (attachment, proptag);
+	if (streamed) {
+		*cb = streamed->cb;
+		*lpb = streamed->lpb;
+
+		return TRUE;
+	}
+
+	bin = e_mapi_util_find_array_propval (&attachment->properties, proptag);
+	if (bin) {
+		*cb = bin->cb;
+		*lpb = bin->lpb;
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
 EMapiObject *
 e_mapi_object_new (TALLOC_CTX *mem_ctx)
 {
@@ -6853,6 +6948,8 @@ e_mapi_object_new (TALLOC_CTX *mem_ctx)
 
 	object->properties.cValues = 0;
 	object->properties.lpProps = talloc_zero_array (mem_ctx, struct mapi_SPropValue, 1);
+	object->streamed_properties = NULL;
+	object->streamed_properties_count = 0;
 	object->recipients = NULL;
 	object->attachments = NULL;
 	object->parent = NULL;
@@ -6887,6 +6984,7 @@ e_mapi_object_free (EMapiObject *object)
 		e_mapi_attachment_free (a);
 	}
 
+	talloc_free (object->streamed_properties);
 	talloc_free (object->properties.lpProps);
 	talloc_free (object);
 }
@@ -6933,6 +7031,85 @@ e_mapi_object_add_attachment (EMapiObject *object,
 	}
 }
 
+void
+e_mapi_object_add_streamed (EMapiObject *object,
+			    uint32_t proptag,
+			    uint64_t cb,
+			    const uint8_t *lpb)
+{
+	guint32 index;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (proptag != 0);
+	g_return_if_fail (e_mapi_object_get_streamed (object, proptag) == NULL);
+
+	object->streamed_properties = talloc_realloc (object,
+		object->streamed_properties,
+		EMapiStreamedProp,
+		object->streamed_properties_count + 1);
+	g_return_if_fail (object->streamed_properties != NULL);
+
+	index = object->streamed_properties_count;
+	object->streamed_properties_count++;
+	object->streamed_properties[index].proptag = proptag;
+	object->streamed_properties[index].cb = cb;
+	object->streamed_properties[index].lpb = lpb;
+}
+
+EMapiStreamedProp *
+e_mapi_object_get_streamed (EMapiObject *object,
+			    uint32_t proptag)
+{
+	guint32 ii;
+
+	g_return_val_if_fail (object != NULL, NULL);
+
+	if (!object->streamed_properties_count || !object->streamed_properties)
+		return NULL;
+
+	for (ii = 0; ii < object->streamed_properties_count; ii++) {
+		if (object->streamed_properties[ii].proptag == proptag)
+			return &object->streamed_properties[ii];
+	}
+
+	return NULL;
+}
+
+gboolean
+e_mapi_object_get_bin_prop (EMapiObject *object,
+			    uint32_t proptag,
+			    uint64_t *cb,
+			    const uint8_t **lpb)
+{
+	EMapiStreamedProp *streamed;
+	const struct SBinary_short *bin;
+
+	g_return_val_if_fail (object != NULL, FALSE);
+	g_return_val_if_fail (cb != NULL, FALSE);
+	g_return_val_if_fail (lpb != NULL, FALSE);
+
+	*cb = 0;
+	*lpb = NULL;
+
+	streamed = e_mapi_object_get_streamed (object, proptag);
+	if (streamed) {
+		*cb = streamed->cb;
+		*lpb = streamed->lpb;
+
+		return TRUE;
+	}
+
+	bin = e_mapi_util_find_array_propval (&object->properties, proptag);
+	if (bin) {
+		*cb = bin->cb;
+		*lpb = bin->lpb;
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
 EMapiPermissionEntry *
 e_mapi_permission_entry_new (const gchar *username,
 			     const struct SBinary_short *entry_id,
diff --git a/src/libexchangemapi/e-mapi-connection.h b/src/libexchangemapi/e-mapi-connection.h
index a32e2e7..8889c55 100644
--- a/src/libexchangemapi/e-mapi-connection.h
+++ b/src/libexchangemapi/e-mapi-connection.h
@@ -61,24 +61,27 @@ typedef struct {
 	time_t last_modified;	/* PidTagLastModificationTime as UTC */
 } ListObjectsData;
 
-struct _EMapiObject;
-struct _EMapiRecipient;
-struct _EMapiAttachment;
+typedef struct _EMapiStreamedProp {
+	uint32_t proptag;
+	uint64_t cb;
+	const uint8_t *lpb; /* taken from the original mapi prop, no need to copy the memory */
+} EMapiStreamedProp;
 
-typedef struct _EMapiObject EMapiObject;
 typedef struct _EMapiRecipient EMapiRecipient;
 typedef struct _EMapiAttachment EMapiAttachment;
+typedef struct _EMapiObject EMapiObject;
 
-struct _EMapiRecipient
-{
+struct _EMapiRecipient {
 	struct mapi_SPropValue_array properties;
 
 	EMapiRecipient *next;
 };
 
-struct _EMapiAttachment
-{
+struct _EMapiAttachment {
 	struct mapi_SPropValue_array properties;
+	EMapiStreamedProp *streamed_properties; /* use get/add functions for these */
+	guint32 streamed_properties_count;
+
 	EMapiObject *embedded_object;
 
 	EMapiAttachment *next;
@@ -86,6 +89,9 @@ struct _EMapiAttachment
 
 struct _EMapiObject {
 	struct mapi_SPropValue_array properties;
+	EMapiStreamedProp *streamed_properties; /* use get/add functions for these */
+	guint32 streamed_properties_count;
+
 	EMapiRecipient *recipients; /* NULL when none */
 	EMapiAttachment *attachments; /* NULL when none */
 
@@ -97,6 +103,16 @@ void			e_mapi_recipient_free		(EMapiRecipient *recipient);
 
 EMapiAttachment *	e_mapi_attachment_new		(TALLOC_CTX *mem_ctx);
 void			e_mapi_attachment_free		(EMapiAttachment *attachment);
+void			e_mapi_attachment_add_streamed	(EMapiAttachment *attachment,
+							 uint32_t proptag,
+							 uint64_t cb,
+							 const uint8_t *lpb); /* this might be created inside the attachment TALLOC_CTX */
+EMapiStreamedProp *	e_mapi_attachment_get_streamed	(EMapiAttachment *attachment,
+							 uint32_t proptag);
+gboolean		e_mapi_attachment_get_bin_prop	(EMapiAttachment *attachment,
+							 uint32_t proptag,
+							 uint64_t *cb,
+							 const uint8_t **lpb);
 
 EMapiObject *		e_mapi_object_new		(TALLOC_CTX *mem_ctx);
 void			e_mapi_object_free		(EMapiObject *object);
@@ -104,6 +120,16 @@ void			e_mapi_object_add_recipient	(EMapiObject *object,
 							 EMapiRecipient *recipient);
 void			e_mapi_object_add_attachment	(EMapiObject *object,
 							 EMapiAttachment *attachment);
+void			e_mapi_object_add_streamed	(EMapiObject *object,
+							 uint32_t proptag,
+							 uint64_t cb,
+							 const uint8_t *lpb); /* this might be created inside the attachment TALLOC_CTX */
+EMapiStreamedProp *	e_mapi_object_get_streamed	(EMapiObject *object,
+							 uint32_t proptag);
+gboolean		e_mapi_object_get_bin_prop	(EMapiObject *object,
+							 uint32_t proptag,
+							 uint64_t *cb,
+							 const uint8_t **lpb);
 
 #define E_MAPI_PERMISSION_MEMBER_ID_ANONYMOUS_CLIENT	(~((uint64_t) 0))
 #define E_MAPI_PERMISSION_MEMBER_ID_DEFAULT_USER	((uint64_t) 0)
diff --git a/src/libexchangemapi/e-mapi-debug.c b/src/libexchangemapi/e-mapi-debug.c
index 994ed32..835a8e1 100644
--- a/src/libexchangemapi/e-mapi-debug.c
+++ b/src/libexchangemapi/e-mapi-debug.c
@@ -867,6 +867,49 @@ e_mapi_debug_dump_properties (struct mapi_SPropValue_array *properties,
 	}
 }
 
+static void
+e_mapi_debug_dump_streamed_properties (guint32 streamed_properties_count,
+				       const EMapiStreamedProp *streamed_properties,
+				       gint indent)
+{
+	guint32 ii;
+
+	if (!streamed_properties || streamed_properties_count <= 0)
+		return;
+
+	for (ii = 0; ii < streamed_properties_count; ii++) {
+		const gchar *tmp;
+
+		tmp = get_proptag_name (streamed_properties[ii].proptag);
+		if (!tmp || !*tmp)
+			tmp = get_namedid_name (streamed_properties[ii].proptag);
+
+		if (tmp && *tmp)
+			g_print ("%*s%s ", indent, "", tmp);
+		else
+			g_print ("%*s0x%08X   ", indent, "", streamed_properties[ii].proptag);
+
+		switch (streamed_properties[ii].proptag & 0xFFFF) {
+		case PT_STRING8:
+			g_print (" (streamed string) - '%s'", streamed_properties[ii].cb == 0 ? "" : streamed_properties[ii].lpb ? (const gchar *) streamed_properties[ii].lpb : "null");
+			break;
+		case PT_UNICODE:
+			g_print (" (streamed unicodestring) - '%s'", streamed_properties[ii].cb == 0 ? "" : streamed_properties[ii].lpb ? (const gchar *) streamed_properties[ii].lpb : "null");
+			break;
+		case PT_BINARY:
+			g_print (" (streamed Binary %p, size %" G_GINT64_MODIFIER "d): %s", streamed_properties[ii].lpb, streamed_properties[ii].cb, streamed_properties[ii].cb > 0 ? "\n" : "");
+			e_mapi_debug_dump_bin (streamed_properties[ii].lpb, streamed_properties[ii].cb, indent + 3);
+			break;
+		default:
+			g_print (" (other streamed type %p, size %" G_GINT64_MODIFIER "d): %s", streamed_properties[ii].lpb, streamed_properties[ii].cb, streamed_properties[ii].cb > 0 ? "\n" : "");
+			e_mapi_debug_dump_bin (streamed_properties[ii].lpb, streamed_properties[ii].cb, indent + 3);
+			break;
+		}
+
+		g_print ("\n");
+	}
+}
+
 void
 e_mapi_debug_dump_object (EMapiObject *object, gboolean with_properties, gint indent)
 {
@@ -879,8 +922,10 @@ e_mapi_debug_dump_object (EMapiObject *object, gboolean with_properties, gint in
 	if (!object)
 		return;
 
-	if (with_properties)
+	if (with_properties) {
 		e_mapi_debug_dump_properties (&object->properties, indent + 3);
+		e_mapi_debug_dump_streamed_properties (object->streamed_properties_count, object->streamed_properties, indent + 3);
+	}
 
 	for (index = 0, recipient = object->recipients; recipient; index++, recipient = recipient->next) {
 		g_print ("%*sRecipient[%d]:\n", indent + 2, "", index);
@@ -890,8 +935,11 @@ e_mapi_debug_dump_object (EMapiObject *object, gboolean with_properties, gint in
 
 	for (index = 0, attachment = object->attachments; attachment; index++, attachment = attachment->next) {
 		g_print ("%*sAttachment[%d]:\n", indent + 2, "", index);
-		if (with_properties)
+		if (with_properties) {
 			e_mapi_debug_dump_properties (&attachment->properties, indent + 3);
+			e_mapi_debug_dump_streamed_properties (attachment->streamed_properties_count, attachment->streamed_properties, indent + 3);
+		}
+
 		if (attachment->embedded_object) {
 			g_print ("%*sEmbedded object:\n", indent + 3, "");
 			e_mapi_debug_dump_object (attachment->embedded_object, with_properties, indent + 5);
diff --git a/src/libexchangemapi/e-mapi-fast-transfer.c b/src/libexchangemapi/e-mapi-fast-transfer.c
index 30ba551..1d36496 100644
--- a/src/libexchangemapi/e-mapi-fast-transfer.c
+++ b/src/libexchangemapi/e-mapi-fast-transfer.c
@@ -51,6 +51,10 @@ struct _EMapiFXParserClosure {
 	uint32_t marker;
 	/* where to store read properties */
 	struct mapi_SPropValue_array *current_properties;
+	TALLOC_CTX *current_streamed_mem_ctx;
+	EMapiStreamedProp **current_streamed_properties;
+	guint32 *current_streamed_properties_count;
+	
 	/* what object is currently read (can be embeded object or the below object */
 	EMapiObject *current_object;
 
@@ -113,6 +117,9 @@ parse_marker_cb (uint32_t marker, void *closure)
 				data->object = NULL;
 				data->current_object = NULL;
 				data->current_properties = NULL;
+				data->current_streamed_mem_ctx = NULL;
+				data->current_streamed_properties = NULL;
+				data->current_streamed_properties_count = NULL;
 			}
 
 			if (stop)
@@ -123,6 +130,9 @@ parse_marker_cb (uint32_t marker, void *closure)
 			data->object = e_mapi_object_new (data->mem_ctx);
 			data->current_object = data->object;
 			data->current_properties = &data->object->properties;
+			data->current_streamed_mem_ctx = data->object;
+			data->current_streamed_properties = &data->object->streamed_properties;
+			data->current_streamed_properties_count = &data->object->streamed_properties_count;
 			data->marker = marker;
 			break;
 		case PidTagEndMessage:
@@ -136,6 +146,9 @@ parse_marker_cb (uint32_t marker, void *closure)
 				data->object = NULL;
 				data->current_object = NULL;
 				data->current_properties = NULL;
+				data->current_streamed_mem_ctx = NULL;
+				data->current_streamed_properties = NULL;
+				data->current_streamed_properties_count = NULL;
 
 				if (stop)
 					return MAPI_E_USER_CANCEL;
@@ -155,11 +168,17 @@ parse_marker_cb (uint32_t marker, void *closure)
 				data->current_object->recipients = recipient;
 
 				data->current_properties = &recipient->properties;
+				data->current_streamed_mem_ctx = NULL;
+				data->current_streamed_properties = NULL;
+				data->current_streamed_properties_count = NULL;
 			}
 			data->marker = marker;
 			break;
 		case PidTagEndToRecip:
 			data->current_properties = NULL;
+			data->current_streamed_mem_ctx = NULL;
+			data->current_streamed_properties = NULL;
+			data->current_streamed_properties_count = NULL;
 			data->marker = 0;
 			break;
 		case PidTagNewAttach:
@@ -175,11 +194,17 @@ parse_marker_cb (uint32_t marker, void *closure)
 				data->current_object->attachments = attachment;
 
 				data->current_properties = &attachment->properties;
+				data->current_streamed_mem_ctx = attachment;
+				data->current_streamed_properties = &attachment->streamed_properties;
+				data->current_streamed_properties_count = &attachment->streamed_properties_count;
 			}
 			data->marker = marker;
 			break;
 		case PidTagEndAttach:
 			data->current_properties = NULL;
+			data->current_streamed_mem_ctx = NULL;
+			data->current_streamed_properties = NULL;
+			data->current_streamed_properties_count = NULL;
 			data->marker = 0;
 			break;
 		case PidTagStartEmbed:
@@ -198,6 +223,9 @@ parse_marker_cb (uint32_t marker, void *closure)
 				data->current_object->attachments->embedded_object = object;
 				data->current_object = object;
 				data->current_properties = &object->properties;
+				data->current_streamed_mem_ctx = object;
+				data->current_streamed_properties = &object->streamed_properties;
+				data->current_streamed_properties_count = &object->streamed_properties_count;
 			}
 			data->marker = marker;
 			break;
@@ -210,6 +238,9 @@ parse_marker_cb (uint32_t marker, void *closure)
 				e_mapi_object_finish_read (data->current_object);
 				data->current_object = data->current_object->parent;
 				data->current_properties = NULL;
+				data->current_streamed_mem_ctx = NULL;
+				data->current_streamed_properties = NULL;
+				data->current_streamed_properties_count = NULL;
 			}
 			data->marker = 0;
 			break;
@@ -274,6 +305,24 @@ parse_property_cb (struct SPropValue prop, void *closure)
 	}
 
 	switch (prop.ulPropTag & 0xFFFF) {
+		case PT_BINARY:
+			if (data->current_streamed_properties && data->current_streamed_properties_count &&
+			    prop.value.bin.cb > 65535) {
+				guint32 index;
+
+				(*data->current_streamed_properties) = talloc_realloc (data->current_streamed_mem_ctx,
+					(*data->current_streamed_properties),
+					EMapiStreamedProp,
+					(*data->current_streamed_properties_count) + 1);
+				index = (*data->current_streamed_properties_count);
+				(*data->current_streamed_properties_count)++;
+				(*data->current_streamed_properties)[index].proptag = prop.ulPropTag;
+				(*data->current_streamed_properties)[index].cb = prop.value.bin.cb;
+				(*data->current_streamed_properties)[index].lpb = prop.value.bin.lpb;
+				break;
+			} else if (prop.value.bin.cb > 65535) {
+				g_debug ("%s: PT_BINARY property 0x%X larger than 64KB (%d), will be truncated", G_STRFUNC, prop.ulPropTag, prop.value.bin.cb);
+			}
 		case PT_BOOLEAN:
 		case PT_I2:
 		case PT_LONG:
@@ -282,7 +331,6 @@ parse_property_cb (struct SPropValue prop, void *closure)
 		case PT_STRING8:
 		case PT_UNICODE:
 		case PT_SYSTIME:
-		case PT_BINARY:
 		case PT_ERROR:
 		case PT_CLSID:
 		case PT_SVREID:
@@ -336,6 +384,9 @@ e_mapi_fast_transfer_internal (EMapiConnection *conn,
 	data.objects_total = objects_total;
 	data.marker = 0;
 	data.current_properties = NULL;
+	data.current_streamed_mem_ctx = NULL;
+	data.current_streamed_properties = NULL;
+	data.current_streamed_properties_count = NULL;
 	data.current_object = NULL;
 	data.object = NULL;
 
@@ -344,6 +395,9 @@ e_mapi_fast_transfer_internal (EMapiConnection *conn,
 		data.object = e_mapi_object_new (data.mem_ctx);
 		data.current_object = data.object;
 		data.current_properties = &data.object->properties;
+		data.current_streamed_mem_ctx = data.object;
+		data.current_streamed_properties = &data.object->streamed_properties;
+		data.current_streamed_properties_count = &data.object->streamed_properties_count;
 		data.marker = PidTagStartMessage;
 	}
 		
diff --git a/src/libexchangemapi/e-mapi-mail-utils.c b/src/libexchangemapi/e-mapi-mail-utils.c
index b931247..bf0e650 100644
--- a/src/libexchangemapi/e-mapi-mail-utils.c
+++ b/src/libexchangemapi/e-mapi-mail-utils.c
@@ -177,7 +177,7 @@ build_body_part_content (CamelMimePart *part, EMapiObject *object, uint32_t prop
 	camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_8BIT);
 
 	value = e_mapi_util_find_array_propval (&object->properties, proptag);
-	if (value) {
+	if (value || (proptag == PidTagHtml && e_mapi_object_get_streamed (object, proptag))) {
 		const gchar *type = NULL;
 		gchar *buff = NULL, *in_utf8;
 		const uint32_t *pcpid = e_mapi_util_find_array_propval (&object->properties, PidTagInternetCodepage);
@@ -214,12 +214,19 @@ build_body_part_content (CamelMimePart *part, EMapiObject *object, uint32_t prop
 		in_utf8 = NULL;
 
 		if (proptag == PidTagHtml) {
-			const struct SBinary_short *html_bin = value;
+			uint64_t cb = 0;
+			const uint8_t *lpb = NULL;
 
-			if (e_mapi_utils_ensure_utf8_string (proptag, pcpid, html_bin->lpb, html_bin->cb, &in_utf8))
+			if (!e_mapi_object_get_bin_prop (object, proptag, &cb, &lpb)) {
+				g_warn_if_reached ();
+				cb = 0;
+				lpb = (const uint8_t *) "";
+			}
+
+			if (e_mapi_utils_ensure_utf8_string (proptag, pcpid, lpb, cb, &in_utf8))
 				camel_mime_part_set_content (part, in_utf8, strlen (in_utf8), type);
 			else
-				camel_mime_part_set_content (part, (const gchar *) html_bin->lpb, html_bin->cb, type);
+				camel_mime_part_set_content (part, (const gchar *) lpb, cb, type);
 			
 		} else {
 			const gchar *str = value;
@@ -240,33 +247,35 @@ static gboolean
 is_apple_attach (EMapiAttachment *attach, guint32 *data_len, guint32 *resource_len)
 {
 	gboolean is_apple = FALSE;
-	const struct SBinary_short *encoding_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachEncoding);
+	uint64_t enc_cb = 0;
+	const uint8_t *enc_lpb = NULL;
 	guint8 apple_enc_magic[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x14, 0x03, 0x0B, 0x01 };
 
-	if (encoding_bin && encoding_bin->lpb && encoding_bin->cb == G_N_ELEMENTS (apple_enc_magic)) {
+	if (e_mapi_attachment_get_bin_prop (attach, PidTagAttachEncoding, &enc_cb, &enc_lpb) && enc_cb == G_N_ELEMENTS (apple_enc_magic)) {
 		gint idx;
 
 		is_apple = TRUE;
-		for (idx = 0; idx < encoding_bin->cb && is_apple; idx++) {
-			is_apple = apple_enc_magic[idx] == encoding_bin->lpb[idx];
+		for (idx = 0; idx < enc_cb && is_apple; idx++) {
+			is_apple = apple_enc_magic[idx] == enc_lpb[idx];
 		}
 	}
 
 	if (is_apple) {
 		/* check boundaries too */
-		const struct SBinary_short *data_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachDataBinary);
+		uint64_t data_cb = 0;
+		const uint8_t *data_lpb = NULL;
 
-		is_apple = data_bin && data_bin->lpb && data_bin->cb > 128;
+		is_apple = e_mapi_attachment_get_bin_prop (attach, PidTagAttachDataBinary, &data_cb, &data_lpb) && data_lpb && data_cb > 128;
 
 		if (is_apple) {
-			const guint8 *bin = data_bin->lpb;
+			const guint8 *bin = data_lpb;
 
 			/* in big-endian format */
 			*data_len = (bin[83] << 24) | (bin[84] << 16) | (bin[85] << 8) | (bin[86]);
 			*resource_len = (bin[87] << 24) | (bin[88] << 16) | (bin[89] << 8) | (bin[90]);
 
 			/* +/- mod 128 (but the first 128 is a header length) */
-			is_apple = 128 + *data_len + *resource_len <= data_bin->cb && bin[1] < 64;
+			is_apple = 128 + *data_len + *resource_len <= data_cb && bin[1] < 64;
 		}
 	}
 
@@ -364,12 +373,12 @@ classify_attachments (EMapiConnection *conn, EMapiAttachment *attachments, const
 		CamelContentType *content_type;
 		CamelMimePart *part;
 		const uint32_t *ui32;
-		const struct SBinary_short *data_bin;
+		uint64_t data_cb = 0;
+		const uint8_t *data_lpb = NULL;
 		gboolean is_apple;
 		guint32 apple_data_len = 0, apple_resource_len = 0;
 
-		data_bin = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachDataBinary);
-		if (!data_bin && !attach->embedded_object) {
+		if (!e_mapi_attachment_get_bin_prop (attach, PidTagAttachDataBinary, &data_cb, &data_lpb) && !attach->embedded_object) {
 			g_debug ("%s: Skipping attachment without data and without embedded object", G_STRFUNC);
 			continue;
 		}
@@ -403,7 +412,8 @@ classify_attachments (EMapiConnection *conn, EMapiAttachment *attachments, const
 		if (is_apple) {
 			CamelMultipart *mp;
 			gchar *apple_filename;
-			const struct SBinary_short *mac_info_bin;
+			uint64_t mac_info_cb = 0;
+			const uint8_t *mac_info_lpb = NULL;
 
 			mp = camel_multipart_new ();
 			camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (mp), "multipart/appledouble");
@@ -411,9 +421,8 @@ classify_attachments (EMapiConnection *conn, EMapiAttachment *attachments, const
 
 			camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
 
-			mac_info_bin = e_mapi_util_find_array_propval (&attach->properties, PidNameAttachmentMacInfo);
-			if (mac_info_bin && mac_info_bin->lpb && mac_info_bin->cb > 0) {
-				camel_mime_part_set_content (part, (const gchar *) mac_info_bin->lpb, mac_info_bin->cb, mime_type);
+			if (e_mapi_attachment_get_bin_prop (attach, PidNameAttachmentMacInfo, &mac_info_cb, &mac_info_lpb) && mac_info_lpb && mac_info_cb > 0) {
+				camel_mime_part_set_content (part, (const gchar *) mac_info_lpb, mac_info_cb, mime_type);
 			} else {
 				/* RFC 1740 */
 				guint8 header[] = {
@@ -434,7 +443,7 @@ classify_attachments (EMapiConnection *conn, EMapiAttachment *attachments, const
 				header[37] = (apple_resource_len      ) & 0xFF;
 
 				g_byte_array_append (arr, header, G_N_ELEMENTS (header));
-				g_byte_array_append (arr, data_bin->lpb + 128 + apple_data_len + (apple_data_len % 128), apple_resource_len);
+				g_byte_array_append (arr, data_lpb + 128 + apple_data_len + (apple_data_len % 128), apple_resource_len);
 
 				camel_mime_part_set_content (part, (const gchar *) arr->data, arr->len, mime_type);
 
@@ -446,7 +455,7 @@ classify_attachments (EMapiConnection *conn, EMapiAttachment *attachments, const
 
 			part = camel_mime_part_new ();
 
-			apple_filename = g_strndup ((const gchar *) data_bin->lpb + 2, data_bin->lpb[1]);
+			apple_filename = g_strndup ((const gchar *) data_lpb + 2, data_lpb[1]);
 			camel_mime_part_set_filename (part, (apple_filename && *apple_filename) ? apple_filename : filename);
 			g_free (apple_filename);
 
@@ -454,7 +463,7 @@ classify_attachments (EMapiConnection *conn, EMapiAttachment *attachments, const
 			if (!mime_type)
 				mime_type = "application/octet-stream";
 
-			camel_mime_part_set_content (part, (const gchar *) data_bin->lpb + 128, apple_data_len, mime_type);
+			camel_mime_part_set_content (part, (const gchar *) data_lpb + 128, apple_data_len, mime_type);
 			camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
 			camel_multipart_add_part (mp, part);
 			g_object_unref (part);
@@ -467,7 +476,7 @@ classify_attachments (EMapiConnection *conn, EMapiAttachment *attachments, const
 			CamelStream *mem;
 
 			mem = camel_stream_mem_new ();
-			camel_stream_write (mem, (const gchar *) data_bin->lpb, data_bin->cb, NULL, NULL);
+			camel_stream_write (mem, (const gchar *) data_lpb, data_cb, NULL, NULL);
 			g_seekable_seek (G_SEEKABLE (mem), 0, G_SEEK_SET, NULL, NULL);
 
 			parser = camel_mime_parser_new ();
@@ -558,11 +567,11 @@ classify_attachments (EMapiConnection *conn, EMapiAttachment *attachments, const
 
 						g_byte_array_free (data, TRUE);
 					} else {
-						camel_mime_part_set_content (part, (const gchar *) data_bin->lpb, data_bin->cb, mime_type);
+						camel_mime_part_set_content (part, (const gchar *) data_lpb, data_cb, mime_type);
 					}
 				}
 			} else {
-				camel_mime_part_set_content (part, (const gchar *) data_bin->lpb, data_bin->cb, mime_type);
+				camel_mime_part_set_content (part, (const gchar *) data_lpb, data_cb, mime_type);
 			}
 
 			content_type = camel_mime_part_get_content_type (part);
@@ -1060,30 +1069,37 @@ get_content_stream (CamelMimePart *part, GCancellable *cancellable)
 
 static void
 e_mapi_mail_content_stream_to_bin (CamelStream *content_stream,
-				   struct SBinary_short *bin,
+				   uint64_t *pcb,
+				   uint8_t **plpb,
 				   TALLOC_CTX *mem_ctx,
 				   GCancellable *cancellable)
 {
 	guint8 *buf;
 	guint32	read_size;
+	uint64_t cb;
+	uint8_t *lpb;
 
 	g_return_if_fail (content_stream != NULL);
-	g_return_if_fail (bin != NULL);
+	g_return_if_fail (pcb != NULL);
+	g_return_if_fail (plpb != NULL);
 	g_return_if_fail (mem_ctx != NULL);
 
 	buf = g_new0 (guint8 , STREAM_SIZE);
 
-	bin->cb = 0;
-	bin->lpb = NULL;
+	cb = 0;
+	lpb = NULL;
 
 	g_seekable_seek (G_SEEKABLE (content_stream), 0, G_SEEK_SET, NULL, NULL);
 	while (read_size = camel_stream_read (content_stream, (gchar *) buf, STREAM_SIZE, cancellable, NULL), read_size > 0) {
-		bin->lpb = talloc_realloc (mem_ctx, bin->lpb, uint8_t, bin->cb + read_size);
-		memcpy (bin->lpb + bin->cb, buf, read_size);
-		bin->cb += read_size;
+		lpb = talloc_realloc (mem_ctx, lpb, uint8_t, cb + read_size);
+		memcpy (lpb + cb, buf, read_size);
+		cb += read_size;
 	}
 
 	g_free (buf);
+
+	*pcb = cb;
+	*plpb = lpb;
 }
 
 #define set_attach_value(pt,vl) {						\
@@ -1103,7 +1119,8 @@ e_mapi_mail_add_attach (EMapiObject *object,
 	CamelContentType *content_type;
 	const gchar *content_id;
 	const gchar *filename;
-	struct SBinary_short bin;
+	uint64_t data_cb = 0;
+	uint8_t *data_lpb = NULL;
 	uint32_t ui32;
 
 	g_return_val_if_fail (object != NULL, FALSE);
@@ -1136,8 +1153,8 @@ e_mapi_mail_add_attach (EMapiObject *object,
 		g_free (ct);
 	}
 
-	e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
-	set_attach_value (PidTagAttachDataBinary, &bin);
+	e_mapi_mail_content_stream_to_bin (content_stream, &data_cb, &data_lpb, attach, cancellable);
+	e_mapi_attachment_add_streamed (attach, PidTagAttachDataBinary, data_cb, data_lpb);
 
 	return TRUE;
 }
@@ -1148,19 +1165,22 @@ e_mapi_mail_add_body (EMapiObject *object,
 		      uint32_t proptag,
 		      GCancellable *cancellable)
 {
-	struct SBinary_short bin = { 0 };
+	uint64_t data_cb = 0;
+	uint8_t *data_lpb = NULL;
 	gchar *str;
 
-	e_mapi_mail_content_stream_to_bin (content_stream, &bin, object, cancellable);
-	str = talloc_strndup (object, (const gchar *) bin.lpb, bin.cb);
-	talloc_free (bin.lpb);
+	e_mapi_mail_content_stream_to_bin (content_stream, &data_cb, &data_lpb, object, cancellable);
+	str = talloc_strndup (object, (const gchar *) data_lpb, data_cb);
+	talloc_free (data_lpb);
 
 	if ((proptag & 0xFFFF) == PT_BINARY) {
-		bin.lpb = (uint8_t *) (str ? str : "");
-		bin.cb = strlen ((const gchar *) bin.lpb) + 1;
-		/* include trailing zero ................ ^^^ */
+		data_lpb = (uint8_t *) (str ? str : "");
+		data_cb = strlen ((const gchar *) data_lpb) + 1;
+		/* include trailing zero .................. ^^^ */
+
+		e_mapi_object_add_streamed (object, proptag, data_cb, data_lpb);
 
-		return e_mapi_utils_add_property (&object->properties, proptag, &bin, object);
+		return TRUE;
 	} else if (str) {
 		if (!e_mapi_utils_add_property (&object->properties, proptag, str, object)) {
 			talloc_free (str);
@@ -1187,7 +1207,8 @@ e_mapi_mail_do_smime_encrypted (EMapiObject *object,
 	CamelDataWrapper *dw;
 	CamelContentType *type;
 	uint32_t ui32;
-	struct SBinary_short bin;
+	uint64_t data_cb = 0;
+	uint8_t *data_lpb = NULL;
 	gchar *content_type_str;
 
 	g_return_val_if_fail (object != NULL, FALSE);
@@ -1220,8 +1241,8 @@ e_mapi_mail_do_smime_encrypted (EMapiObject *object,
 	set_attach_value (PidTagAttachLongFilename, "SMIME.txt");
 	set_attach_value (PidTagDisplayName, "SMIME.txt");
 
-	e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
-	set_attach_value (PidTagAttachDataBinary, &bin);
+	e_mapi_mail_content_stream_to_bin (content_stream, &data_cb, &data_lpb, attach, cancellable);
+	e_mapi_attachment_add_streamed (attach, PidTagAttachDataBinary, data_cb, data_lpb);
 
 	g_object_unref (content_stream);
 
@@ -1240,7 +1261,8 @@ e_mapi_mail_do_smime_signed (EMapiObject *object,
 	CamelContentType *type;
 	CamelDataWrapper *dw;
 	uint32_t ui32;
-	struct SBinary_short bin;
+	uint64_t data_cb = 0;
+	uint8_t *data_lpb = NULL;
 	gchar *content_type_str;
 
 	g_free (*pmsg_class);
@@ -1293,8 +1315,8 @@ e_mapi_mail_do_smime_signed (EMapiObject *object,
 	set_attach_value (PidTagAttachLongFilename, "SMIME.txt");
 	set_attach_value (PidTagDisplayName, "SMIME.txt");
 
-	e_mapi_mail_content_stream_to_bin (content_stream, &bin, attach, cancellable);
-	set_attach_value (PidTagAttachDataBinary, &bin);
+	e_mapi_mail_content_stream_to_bin (content_stream, &data_cb, &data_lpb, attach, cancellable);
+	e_mapi_attachment_add_streamed (attach, PidTagAttachDataBinary, data_cb, data_lpb);
 
 	g_object_unref (content_stream);
 



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