[evolution-mapi/gnome-2-28] Bug #586093 - Text Body larger than 4KB received broken
- From: Milan Crha <mcrha src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [evolution-mapi/gnome-2-28] Bug #586093 - Text Body larger than 4KB received broken
- Date: Fri, 29 Jan 2010 18:30:09 +0000 (UTC)
commit ff76193025daa5c54e963195713aefdd4c34df07
Author: Milan Crha <mcrha redhat com>
Date: Fri Jan 29 19:29:55 2010 +0100
Bug #586093 - Text Body larger than 4KB received broken
src/camel/camel-mapi-folder.c | 156 ++++++++++++++++++++++++++++------------
src/camel/camel-mapi-utils.c | 52 +++++++++-----
2 files changed, 143 insertions(+), 65 deletions(-)
---
diff --git a/src/camel/camel-mapi-folder.c b/src/camel/camel-mapi-folder.c
index 5238528..55d8a4c 100644
--- a/src/camel/camel-mapi-folder.c
+++ b/src/camel/camel-mapi-folder.c
@@ -1299,10 +1299,13 @@ fetch_item_cb (FetchItemsCallbackData *item_data, gpointer data)
item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
item->is_cal = TRUE;
+
+ g_free (appointment_body_str);
} else {
- if (!((body = exchange_mapi_util_find_stream (item_data->streams, PR_HTML)) ||
+ /* always prefer unicode version, as that can be properly read */
+ if (!((body = exchange_mapi_util_find_stream (item_data->streams, PR_BODY_UNICODE)) ||
(body = exchange_mapi_util_find_stream (item_data->streams, PR_BODY))))
- body = exchange_mapi_util_find_stream (item_data->streams, PR_BODY_UNICODE);
+ body = exchange_mapi_util_find_stream (item_data->streams, PR_HTML);
item->msg.body_parts = g_slist_append (item->msg.body_parts, body);
@@ -1422,6 +1425,11 @@ mapi_populate_details_from_item (CamelFolder *folder, CamelMimeMessage *msg, Map
for (h = part->headers; h; h = h->next) {
const gchar *value = h->value;
+ /* skip all headers describing content of a message,
+ because it's overwritten on message decomposition */
+ if (g_ascii_strncasecmp (h->name, "Content", 7) == 0)
+ continue;
+
while (value && camel_mime_is_lwsp (*value))
value++;
@@ -1469,15 +1477,12 @@ mapi_populate_details_from_item (CamelFolder *folder, CamelMimeMessage *msg, Map
static void
-mapi_populate_msg_body_from_item (CamelMultipart *multipart, MapiItem *item, ExchangeMAPIStream *body)
+mapi_populate_msg_body_from_item (CamelMimePart *part, MapiItem *item, ExchangeMAPIStream *body)
{
- CamelMimePart *part;
- const char* type = NULL;
-
- part = camel_mime_part_new ();
- camel_mime_part_set_encoding(part, CAMEL_TRANSFER_ENCODING_8BIT);
+ camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_8BIT);
if (body) {
+ const gchar* type = NULL;
gchar *buff = NULL;
if (item->is_cal)
@@ -1497,14 +1502,36 @@ mapi_populate_msg_body_from_item (CamelMultipart *multipart, MapiItem *item, Exc
camel_mime_part_set_content (part, (const char *) body->value->data, body->value->len, type);
g_free (buff);
- type = NULL;
} else
- camel_mime_part_set_content(part, " ", strlen(" "), "text/html");
-
- camel_multipart_add_part (multipart, part);
- camel_object_unref (part);
+ camel_mime_part_set_content (part, "", strlen (""), "text/plain");
}
+static gint
+sort_bodies_cb (gconstpointer a, gconstpointer b)
+{
+ static const gint desired_order[] = { PR_BODY, PR_BODY_UNICODE, PR_HTML };
+ const ExchangeMAPIStream *stream_a = a, *stream_b = b;
+ gint aidx, bidx;
+
+ if (a == b)
+ return 0;
+ if (!a)
+ return -1;
+ if (!b)
+ return 1;
+
+ for (aidx = 0; aidx < G_N_ELEMENTS (desired_order); aidx++) {
+ if (desired_order[aidx] == stream_a->proptag)
+ break;
+ }
+
+ for (bidx = 0; bidx < G_N_ELEMENTS (desired_order); bidx++) {
+ if (desired_order[bidx] == stream_b->proptag)
+ break;
+ }
+
+ return aidx - bidx;
+}
static CamelMimeMessage *
mapi_folder_item_to_msg( CamelFolder *folder,
@@ -1513,32 +1540,14 @@ mapi_folder_item_to_msg( CamelFolder *folder,
{
CamelMimeMessage *msg = NULL;
CamelMultipart *multipart = NULL;
+ CamelMimePart *part = NULL;
+ CamelDataWrapper *msg_content = NULL;
GSList *attach_list = NULL;
- /* int errno; */
- /* char *body = NULL; */
- ExchangeMAPIStream *body = NULL;
GSList *body_part_list = NULL;
attach_list = item->attachments;
msg = camel_mime_message_new ();
- multipart = camel_multipart_new ();
-
- /*FIXME : Using set of default. Fix it during mimewriter*/
- camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart),
- "multipart/related");
- camel_content_type_set_param(CAMEL_DATA_WRAPPER (multipart)->mime_type,
- "type", "multipart/alternative");
-
- camel_multipart_set_boundary (multipart, NULL);
-
- /* Handle Multipart */
- body_part_list = item->msg.body_parts;
- while (body_part_list){
- body = body_part_list->data;
- mapi_populate_msg_body_from_item (multipart, item, body);
- body_part_list = g_slist_next (body_part_list);
- }
/* Threading */
if (item->header.message_id)
@@ -1550,18 +1559,69 @@ mapi_folder_item_to_msg( CamelFolder *folder,
if (item->header.in_reply_to)
camel_medium_add_header (CAMEL_MEDIUM (msg), "In-Reply-To", item->header.in_reply_to);
- /*Set recipient details*/
+ /* Set recipient details */
mapi_msg_set_recipient_list (msg, item);
mapi_populate_details_from_item (folder, msg, item);
- /** Attachment Handling*/
+ if (g_slist_length (attach_list) > 0) {
+ multipart = camel_multipart_new ();
+ camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart), "multipart/mixed");
+ camel_multipart_set_boundary (multipart, NULL);
+
+ msg_content = CAMEL_DATA_WRAPPER (multipart);
+ }
+
+ if (g_slist_length (item->msg.body_parts) > 1) {
+ multipart = camel_multipart_new ();
+ camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (multipart), "multipart/alternative");
+ camel_multipart_set_boundary (multipart, NULL);
+
+ item->msg.body_parts = g_slist_sort (item->msg.body_parts, sort_bodies_cb);
+
+ /* Handle Multipart */
+ for (body_part_list = item->msg.body_parts; body_part_list; body_part_list = g_slist_next (body_part_list)) {
+ part = camel_mime_part_new ();
+
+ mapi_populate_msg_body_from_item (part, item, body_part_list->data);
+
+ camel_multipart_add_part (CAMEL_MULTIPART (msg_content), part);
+ camel_object_unref (part);
+ }
+
+ if (msg_content) {
+ part = camel_mime_part_new ();
+ camel_data_wrapper_set_mime_type (CAMEL_DATA_WRAPPER (part), "multipart/alternative");
+ camel_medium_set_content_object (CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (multipart));
+ camel_object_unref (multipart);
+
+ camel_multipart_add_part (CAMEL_MULTIPART (msg_content), part);
+ camel_object_unref (part);
+ } else {
+ msg_content = CAMEL_DATA_WRAPPER (multipart);
+ }
+ } else {
+ if (msg_content) {
+ part = camel_mime_part_new ();
+ mapi_populate_msg_body_from_item (part, item, item->msg.body_parts ? item->msg.body_parts->data : NULL);
+ camel_multipart_add_part (CAMEL_MULTIPART (msg_content), part);
+ camel_object_unref (part);
+ } else {
+ msg_content = CAMEL_DATA_WRAPPER (msg);
+ mapi_populate_msg_body_from_item (CAMEL_MIME_PART (msg), item, item->msg.body_parts ? item->msg.body_parts->data : NULL);
+ }
+ }
+
+ /* Attachment Handling */
if (attach_list) {
- GSList *al = attach_list;
+ GSList *al;
+
+ multipart = CAMEL_MULTIPART (msg_content);
+
for (al = attach_list; al != NULL; al = al->next) {
ExchangeMAPIAttachment *attach = (ExchangeMAPIAttachment *)al->data;
ExchangeMAPIStream *stream = NULL;
const char *filename, *mime_type, *content_id = NULL;
- CamelMimePart *part;
+ CamelContentType *content_type;
stream = exchange_mapi_util_find_stream (attach->streams, PR_ATTACH_DATA_BIN);
@@ -1581,8 +1641,9 @@ mapi_folder_item_to_msg( CamelFolder *folder,
camel_content_type_set_param (((CamelDataWrapper *) part)->mime_type, "name", filename);
/*Content-Type*/
- mime_type = (const char *) exchange_mapi_util_find_SPropVal_array_propval(attach->lpProps,
- PR_ATTACH_MIME_TAG);
+ mime_type = (const char *) exchange_mapi_util_find_SPropVal_array_propval (attach->lpProps, PR_ATTACH_MIME_TAG);
+ if (!mime_type)
+ mime_type = "application/octet-stream";
camel_mime_part_set_content (part, (const char *) stream->value->data, stream->value->len, mime_type);
@@ -1592,8 +1653,11 @@ mapi_folder_item_to_msg( CamelFolder *folder,
camel_mime_part_set_content_id (part, content_id);
- /*FIXME : Mime Reader / Writer work*/
- //camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
+ content_type = camel_mime_part_get_content_type (part);
+ if (content_type && camel_content_type_is (content_type, "text", "*"))
+ camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_QUOTEDPRINTABLE);
+ else
+ camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);
camel_multipart_add_part (multipart, part);
camel_object_unref (part);
@@ -1602,16 +1666,14 @@ mapi_folder_item_to_msg( CamelFolder *folder,
exchange_mapi_util_free_attachment_list (&attach_list);
}
- camel_medium_set_content_object(CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER(multipart));
- camel_object_unref (multipart);
-
- if (body)
- g_free (body);
+ if (msg_content != CAMEL_DATA_WRAPPER (msg)) {
+ camel_medium_set_content_object (CAMEL_MEDIUM (msg), msg_content);
+ camel_object_unref (msg_content);
+ }
return msg;
}
-
static CamelMimeMessage *
mapi_folder_get_message( CamelFolder *folder, const char *uid, CamelException *ex )
{
diff --git a/src/camel/camel-mapi-utils.c b/src/camel/camel-mapi-utils.c
index 657f3e2..50d5eb4 100644
--- a/src/camel/camel-mapi-utils.c
+++ b/src/camel/camel-mapi-utils.c
@@ -133,18 +133,17 @@ mapi_item_set_body_stream (MapiItem *item, CamelStream *body, MapiItemPartType p
guint8 *buf = g_new0 (guint8 , STREAM_SIZE);
guint32 read_size = 0, i;
ExchangeMAPIStream *stream = g_new0 (ExchangeMAPIStream, 1);
- gboolean contains_only_7bit = TRUE;
+ gboolean contains_only_7bit = TRUE, is_null_terminated = FALSE;
camel_seekable_stream_seek((CamelSeekableStream *)body, 0, CAMEL_STREAM_SET);
stream->value = g_byte_array_new ();
- while((read_size = camel_stream_read(body, (char *)buf, STREAM_SIZE))){
- if (read_size == -1)
- return;
-
+ while (read_size = camel_stream_read (body, (char *)buf, STREAM_SIZE), read_size > 0){
stream->value = g_byte_array_append (stream->value, buf, read_size);
+ is_null_terminated = buf [read_size - 1] == 0;
+
for (i = 0; i < read_size && contains_only_7bit; i++) {
contains_only_7bit = buf[i] < 128;
}
@@ -162,22 +161,26 @@ mapi_item_set_body_stream (MapiItem *item, CamelStream *body, MapiItemPartType p
}
if (stream->value->len < MAX_READ_SIZE && contains_only_7bit) {
+ if (!is_null_terminated)
+ g_byte_array_append (stream->value, (const guint8 *)"", 1);
+
item->msg.body_parts = g_slist_append (item->msg.body_parts, stream);
} else {
gsize written = 0;
gchar *in_unicode;
- guint8 byte = 0;
- while (stream->value->len > 0 && !stream->value->data [stream->value->len - 1]) {
+ if (is_null_terminated)
stream->value->len--;
- }
+
/* convert to unicode, because stream is supposed to be in it */
in_unicode = g_convert ((const gchar *)stream->value->data, stream->value->len, "UTF-16", "UTF-8", NULL, &written, NULL);
if (in_unicode && written > 0) {
g_byte_array_set_size (stream->value, 0);
g_byte_array_append (stream->value, (const guint8 *) in_unicode, written);
- g_byte_array_append (stream->value, &byte, 1);
- g_byte_array_append (stream->value, &byte, 1);
+
+ /* null-terminated unicode string */
+ g_byte_array_append (stream->value, (const guint8 *)"", 1);
+ g_byte_array_append (stream->value, (const guint8 *)"", 1);
}
g_free (in_unicode);
@@ -192,6 +195,7 @@ mapi_item_add_attach (MapiItem *item, CamelMimePart *part, CamelStream *content_
guint8 *buf = g_new0 (guint8 , STREAM_SIZE);
const gchar *content_id = NULL;
guint32 read_size, flag, i = 0;
+ CamelContentType *content_type;
ExchangeMAPIAttachment *item_attach;
ExchangeMAPIStream *stream;
@@ -200,7 +204,7 @@ mapi_item_add_attach (MapiItem *item, CamelMimePart *part, CamelStream *content_
item_attach = g_new0 (ExchangeMAPIAttachment, 1);
- item_attach->lpProps = g_new0 (struct SPropValue, 5);
+ item_attach->lpProps = g_new0 (struct SPropValue, 6);
flag = ATTACH_BY_VALUE;
set_SPropValue_proptag(&(item_attach->lpProps[i++]), PR_ATTACH_METHOD, (const void *) (&flag));
@@ -231,6 +235,16 @@ mapi_item_add_attach (MapiItem *item, CamelMimePart *part, CamelStream *content_
(const void *) g_strdup(content_id));
}
+ content_type = camel_mime_part_get_content_type (part);
+ if (content_type) {
+ gchar *ct = camel_content_type_simple (content_type);
+ if (ct) {
+ set_SPropValue_proptag (&(item_attach->lpProps[i++]),
+ PR_ATTACH_MIME_TAG,
+ (const void *) ct);
+ }
+ }
+
item_attach->cValues = i;
stream = g_new0 (ExchangeMAPIStream, 1);
@@ -238,7 +252,7 @@ mapi_item_add_attach (MapiItem *item, CamelMimePart *part, CamelStream *content_
stream->value = g_byte_array_new ();
camel_seekable_stream_seek((CamelSeekableStream *)content_stream, 0, CAMEL_STREAM_SET);
- while((read_size = camel_stream_read(content_stream, (char *)buf, STREAM_SIZE))){
+ while (read_size = camel_stream_read(content_stream, (char *)buf, STREAM_SIZE), read_size > 0) {
stream->value = g_byte_array_append (stream->value, buf, read_size);
}
@@ -249,7 +263,7 @@ mapi_item_add_attach (MapiItem *item, CamelMimePart *part, CamelStream *content_
}
static gboolean
-mapi_do_multipart(CamelMultipart *mp, MapiItem *item)
+mapi_do_multipart (CamelMultipart *mp, MapiItem *item, gboolean *is_first)
{
CamelDataWrapper *dw;
CamelStream *content_stream;
@@ -261,6 +275,8 @@ mapi_do_multipart(CamelMultipart *mp, MapiItem *item)
const gchar *content_id;
gint content_size;
+ g_return_val_if_fail (is_first != NULL, FALSE);
+
n_part = camel_multipart_get_number(mp);
for (i_part = 0; i_part < n_part; i_part++) {
/* getting part */
@@ -268,7 +284,7 @@ mapi_do_multipart(CamelMultipart *mp, MapiItem *item)
dw = camel_medium_get_content_object (CAMEL_MEDIUM (part));
if (CAMEL_IS_MULTIPART(dw)) {
/* recursive */
- if (!mapi_do_multipart(CAMEL_MULTIPART(dw), item))
+ if (!mapi_do_multipart (CAMEL_MULTIPART (dw), item, is_first))
return FALSE;
continue ;
}
@@ -277,7 +293,6 @@ mapi_do_multipart(CamelMultipart *mp, MapiItem *item)
content_stream = camel_stream_mem_new();
content_size = camel_data_wrapper_decode_to_stream (dw, (CamelStream *) content_stream);
- camel_stream_write ((CamelStream *) content_stream, "", 1);
camel_seekable_stream_seek((CamelSeekableStream *)content_stream, 0, CAMEL_STREAM_SET);
@@ -286,8 +301,9 @@ mapi_do_multipart(CamelMultipart *mp, MapiItem *item)
type = camel_mime_part_get_content_type(part);
- if (i_part == 0 && camel_content_type_is (type, "text", "plain")) {
+ if (i_part == 0 && (*is_first) && camel_content_type_is (type, "text", "plain")) {
mapi_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT);
+ *is_first = FALSE;
} else if (camel_content_type_is (type, "text", "html")) {
mapi_item_set_body_stream (item, content_stream, PART_TYPE_TEXT_HTML);
} else {
@@ -355,7 +371,8 @@ camel_mapi_utils_mime_to_item (CamelMimeMessage *message, CamelAddress *from, Ca
multipart = (CamelMultipart *)camel_medium_get_content_object (CAMEL_MEDIUM (message));
if (CAMEL_IS_MULTIPART(multipart)) {
- if (mapi_do_multipart(CAMEL_MULTIPART(multipart), item))
+ gboolean is_first = TRUE;
+ if (!mapi_do_multipart (CAMEL_MULTIPART(multipart), item, &is_first))
printf("camel message multi part error\n");
} else {
dw = camel_medium_get_content_object (CAMEL_MEDIUM (message));
@@ -365,7 +382,6 @@ camel_mapi_utils_mime_to_item (CamelMimeMessage *message, CamelAddress *from, Ca
content_stream = (CamelStream *)camel_stream_mem_new();
content_size = camel_data_wrapper_decode_to_stream(dw, (CamelStream *)content_stream);
- camel_stream_write ((CamelStream *) content_stream, "", 1);
mapi_item_set_body_stream (item, content_stream, PART_TYPE_PLAIN_TEXT);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]