[gmime] Redesigned the way header values get cached by the parser to save original formatting.



commit 6fff6564e21a1aba79fe5d86b3e8035c48a653c1
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Mon Jan 30 21:38:14 2017 -0500

    Redesigned the way header values get cached by the parser to save original formatting.
    
    Fixes https://bugzilla.gnome.org/show_bug.cgi?id=635445

 gmime/gmime-application-pkcs7-mime.c |   18 +-
 gmime/gmime-header.c                 |  322 ++++++++++++++++++----------------
 gmime/gmime-header.h                 |   15 ++-
 gmime/gmime-message-part.c           |   28 ++--
 gmime/gmime-message-partial.c        |   30 ++--
 gmime/gmime-message.c                |  234 ++++++++++++------------
 gmime/gmime-multipart.c              |   39 ++--
 gmime/gmime-object.c                 |   67 +++++--
 gmime/gmime-object.h                 |    8 +-
 gmime/gmime-parser.c                 |  129 ++++----------
 gmime/gmime-part.c                   |   56 ++++---
 tests/test-parser.c                  |    3 -
 12 files changed, 476 insertions(+), 473 deletions(-)
---
diff --git a/gmime/gmime-application-pkcs7-mime.c b/gmime/gmime-application-pkcs7-mime.c
index 10ccebe..19f940d 100644
--- a/gmime/gmime-application-pkcs7-mime.c
+++ b/gmime/gmime-application-pkcs7-mime.c
@@ -38,9 +38,9 @@ static void g_mime_application_pkcs7_mime_init (GMimeApplicationPkcs7Mime *catpa
 static void g_mime_application_pkcs7_mime_finalize (GObject *object);
 
 /* GMimeObject class methods */
-static void application_pkcs7_mime_prepend_header (GMimeObject *object, const char *header, const char 
*value);
-static void application_pkcs7_mime_append_header (GMimeObject *object, const char *header, const char 
*value);
-static void application_pkcs7_mime_set_header (GMimeObject *object, const char *header, const char *value);
+static void application_pkcs7_mime_prepend_header (GMimeObject *object, const char *header, const char 
*value, const char *raw_value, gint64 offset);
+static void application_pkcs7_mime_append_header (GMimeObject *object, const char *header, const char 
*value, const char *raw_value, gint64 offset);
+static void application_pkcs7_mime_set_header (GMimeObject *object, const char *header, const char *value, 
const char *raw_value, gint64 offset);
 static const char *application_pkcs7_mime_get_header (GMimeObject *object, const char *header);
 static gboolean application_pkcs7_mime_remove_header (GMimeObject *object, const char *header);
 static void application_pkcs7_mime_set_content_type (GMimeObject *object, GMimeContentType *content_type);
@@ -105,21 +105,21 @@ g_mime_application_pkcs7_mime_finalize (GObject *object)
 }
 
 static void
-application_pkcs7_mime_prepend_header (GMimeObject *object, const char *header, const char *value)
+application_pkcs7_mime_prepend_header (GMimeObject *object, const char *header, const char *value, const 
char *raw_value, gint64 offset)
 {
-       GMIME_OBJECT_CLASS (parent_class)->prepend_header (object, header, value);
+       GMIME_OBJECT_CLASS (parent_class)->prepend_header (object, header, value, raw_value, offset);
 }
 
 static void
-application_pkcs7_mime_append_header (GMimeObject *object, const char *header, const char *value)
+application_pkcs7_mime_append_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset)
 {
-       GMIME_OBJECT_CLASS (parent_class)->append_header (object, header, value);
+       GMIME_OBJECT_CLASS (parent_class)->append_header (object, header, value, raw_value, offset);
 }
 
 static void
-application_pkcs7_mime_set_header (GMimeObject *object, const char *header, const char *value)
+application_pkcs7_mime_set_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset)
 {
-       GMIME_OBJECT_CLASS (parent_class)->set_header (object, header, value);
+       GMIME_OBJECT_CLASS (parent_class)->set_header (object, header, value, raw_value, offset);
 }
 
 static const char *
diff --git a/gmime/gmime-header.c b/gmime/gmime-header.c
index e7b18db..ba9eddc 100644
--- a/gmime/gmime-header.c
+++ b/gmime/gmime-header.c
@@ -45,24 +45,13 @@
  * values.
  **/
 
-
-/**
- * GMimeHeader:
- * @next: pointer to the next header
- * @prev: pointer to the previous header
- * @offset: file/stream offset
- * @name: header name
- * @value: header value
- *
- * A message/rfc822 header.
- **/
-
 struct _GMimeHeader {
        GMimeHeader *next;
        GMimeHeader *prev;
-       /*gint64 offset;*/
+       gint64 offset;
        char *name;
        char *value;
+       char *raw_value;
 };
 
 struct _GMimeHeaderList {
@@ -75,14 +64,11 @@ struct _GMimeHeaderList {
 };
 
 
-static GMimeHeader *g_mime_header_new (const char *name, const char *value, gint64 offset);
-static void g_mime_header_free (GMimeHeader *header);
-
-
 /**
  * g_mime_header_new:
  * @name: header name
  * @value: header value
+ * @raw_value: raw header value
  * @offset: file/stream offset for the start of the header (or %-1 if unknown)
  *
  * Creates a new #GMimeHeader.
@@ -90,14 +76,15 @@ static void g_mime_header_free (GMimeHeader *header);
  * Returns: a new #GMimeHeader with the specified values.
  **/
 static GMimeHeader *
-g_mime_header_new (const char *name, const char *value, gint64 offset)
+g_mime_header_new (const char *name, const char *value, const char *raw_value, gint64 offset)
 {
        GMimeHeader *header;
        
        header = g_slice_new (GMimeHeader);
        header->name = g_strdup (name);
        header->value = g_strdup (value);
-       /*header->offset = offset;*/
+       header->raw_value = raw_value ? g_strdup (raw_value) : NULL;
+       header->offset = offset;
        header->next = NULL;
        header->prev = NULL;
        
@@ -116,6 +103,7 @@ g_mime_header_free (GMimeHeader *header)
 {
        g_free (header->name);
        g_free (header->value);
+       g_free (header->raw_value);
        
        g_slice_free (GMimeHeader, header);
 }
@@ -364,7 +352,6 @@ g_mime_header_iter_prev (GMimeHeaderIter *iter)
 }
 
 
-#if 0
 /**
  * g_mime_header_iter_get_offset:
  * @iter: a #GMimeHeaderIter
@@ -383,7 +370,13 @@ g_mime_header_iter_get_offset (GMimeHeaderIter *iter)
        
        return iter->cursor->offset;
 }
-#endif
+
+
+void
+_g_mime_header_iter_set_offset (GMimeHeaderIter *iter, gint64 offset)
+{
+       iter->cursor->offset = offset;
+}
 
 
 /**
@@ -430,7 +423,8 @@ g_mime_header_iter_set_value (GMimeHeaderIter *iter, const char *value)
        g_free (iter->cursor->value);
        iter->cursor->value = g_strdup (value);
        
-       g_mime_header_list_set_stream (iter->hdrlist, NULL);
+       g_free (iter->cursor->raw_value);
+       iter->cursor->raw_value = NULL;
        
        return TRUE;
 }
@@ -459,6 +453,18 @@ g_mime_header_iter_get_value (GMimeHeaderIter *iter)
 }
 
 
+const char *
+_g_mime_header_iter_get_raw_value (GMimeHeaderIter *iter)
+{
+       g_return_val_if_fail (iter != NULL, NULL);
+       
+       if (!g_mime_header_iter_is_valid (iter))
+               return NULL;
+       
+       return iter->cursor->raw_value;
+}
+
+
 /**
  * g_mime_header_iter_remove:
  * @iter: a #GMimeHeaderIter
@@ -519,6 +525,71 @@ g_mime_header_iter_remove (GMimeHeaderIter *iter)
 }
 
 
+static ssize_t
+default_writer (GMimeStream *stream, const char *name, const char *value)
+{
+       ssize_t nwritten;
+       char *val;
+       
+       val = g_mime_utils_header_printf ("%s: %s\n", name, value);
+       nwritten = g_mime_stream_write_string (stream, val);
+       g_free (val);
+       
+       return nwritten;
+}
+
+
+static ssize_t
+g_mime_header_write_to_stream (GHashTable *writers, GMimeHeader *header, GMimeStream *stream)
+{
+       ssize_t nwritten, total = 0;
+       GMimeHeaderWriter writer;
+       char *val;
+       
+       if (header->raw_value) {
+               val = g_mime_utils_header_printf ("%s:%s", header->name, header->raw_value);
+               nwritten = g_mime_stream_write_string (stream, val);
+               g_free (val);
+               
+               if (nwritten == -1)
+                       return -1;
+               
+               total += nwritten;
+       } else if (header->value) {
+               if (!(writer = g_hash_table_lookup (writers, header->name)))
+                       writer = default_writer;
+               
+               if ((nwritten = writer (stream, header->name, header->value)) == -1)
+                       return -1;
+               
+               total += nwritten;
+       }
+       
+       return total;
+}
+
+
+/**
+ * g_mime_header_iter_write_to_stream:
+ * @iter: a #GMimeHeaderIter
+ * @stream: a #GMimeStream
+ *
+ * Write the header to a stream.
+ *
+ * Returns: the number of bytes written or %-1 on fail.
+ **/
+ssize_t
+g_mime_header_iter_write_to_stream (GMimeHeaderIter *iter, GMimeStream *stream)
+{
+       g_return_val_if_fail (iter != NULL, -1);
+       
+       if (!g_mime_header_iter_is_valid (iter))
+               return -1;
+       
+       return g_mime_header_write_to_stream (iter->hdrlist->writers, iter->cursor, stream);
+}
+
+
 /**
  * g_mime_header_list_new:
  *
@@ -539,7 +610,6 @@ g_mime_header_list_new (void)
                                          g_mime_strcase_equal);
        list_init (&headers->list);
        headers->changed = g_mime_event_new (headers);
-       headers->stream = NULL;
        headers->version = 0;
        
        return headers;
@@ -570,9 +640,6 @@ g_mime_header_list_destroy (GMimeHeaderList *headers)
        g_hash_table_destroy (headers->writers);
        g_hash_table_destroy (headers->hash);
        
-       if (headers->stream)
-               g_object_unref (headers->stream);
-       
        g_mime_event_destroy (headers->changed);
        
        g_slice_free (GMimeHeaderList, headers);
@@ -601,8 +668,6 @@ g_mime_header_list_clear (GMimeHeaderList *headers)
        
        g_hash_table_remove_all (headers->hash);
        list_init (&headers->list);
-       
-       g_mime_header_list_set_stream (headers, NULL);
 }
 
 
@@ -630,6 +695,29 @@ g_mime_header_list_contains (const GMimeHeaderList *headers, const char *name)
 }
 
 
+gboolean
+_g_mime_header_list_has_raw_value (const GMimeHeaderList *headers, const char *name)
+{
+       const GMimeHeader *header;
+       
+       if (!(header = g_hash_table_lookup (headers->hash, name)))
+               return FALSE;
+       
+       return header->raw_value != NULL;
+}
+
+
+void
+_g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char *value, const char 
*raw_value, gint64 offset)
+{
+       GMimeHeader *header;
+       
+       header = g_mime_header_new (name, value, raw_value, offset);
+       list_prepend (&headers->list, (ListNode *) header);
+       g_hash_table_replace (headers->hash, header->name, header);
+}
+
+
 /**
  * g_mime_header_list_prepend:
  * @headers: a #GMimeHeaderList
@@ -646,16 +734,23 @@ g_mime_header_list_contains (const GMimeHeaderList *headers, const char *name)
 void
 g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char *value)
 {
-       GMimeHeader *header;
-       
        g_return_if_fail (headers != NULL);
        g_return_if_fail (name != NULL);
        
-       header = g_mime_header_new (name, value, -1);
-       list_prepend (&headers->list, (ListNode *) header);
-       g_hash_table_replace (headers->hash, header->name, header);
+       _g_mime_header_list_prepend (headers, name, value, NULL, -1);
+}
+
+
+void
+_g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char *value, const char 
*raw_value, gint64 offset)
+{
+       GMimeHeader *header;
        
-       g_mime_header_list_set_stream (headers, NULL);
+       header = g_mime_header_new (name, value, raw_value, offset);
+       list_append (&headers->list, (ListNode *) header);
+       
+       if (!g_hash_table_lookup (headers->hash, name))
+               g_hash_table_insert (headers->hash, header->name, header);
 }
 
 
@@ -675,18 +770,10 @@ g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const ch
 void
 g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char *value)
 {
-       GMimeHeader *header;
-       
        g_return_if_fail (headers != NULL);
        g_return_if_fail (name != NULL);
        
-       header = g_mime_header_new (name, value, -1);
-       list_append (&headers->list, (ListNode *) header);
-       
-       if (!g_hash_table_lookup (headers->hash, name))
-               g_hash_table_insert (headers->hash, header->name, header);
-       
-       g_mime_header_list_set_stream (headers, NULL);
+       _g_mime_header_list_append (headers, name, value, NULL, -1);
 }
 
 
@@ -717,36 +804,20 @@ g_mime_header_list_get (const GMimeHeaderList *headers, const char *name)
 }
 
 
-/**
- * g_mime_header_list_set:
- * @headers: a #GMimeHeaderList
- * @name: header name
- * @value: header value
- *
- * Set the value of the specified header. If @value is %NULL and the
- * header, @name, had not been previously set, a space will be set
- * aside for it (useful for setting the order of headers before values
- * can be obtained for them) otherwise the header will be unset.
- *
- * Note: If there are multiple headers with the specified field name,
- * the first instance of the header will be replaced and further
- * instances will be removed.
- *
- * Additionally, @value should be encoded with a function such as
- * g_mime_utils_header_encode_text().
- **/
 void
-g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value)
+_g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value, const char 
*raw_value, gint64 offset)
 {
        GMimeHeader *header, *next;
        
-       g_return_if_fail (headers != NULL);
-       g_return_if_fail (name != NULL);
-       
        if ((header = g_hash_table_lookup (headers->hash, name))) {
                g_free (header->value);
                header->value = g_strdup (value);
                
+               g_free (header->raw_value);
+               header->raw_value = raw_value ? g_strdup (raw_value) : NULL;
+               
+               header->offset = offset;
+               
                header = header->next;
                while (header->next) {
                        next = header->next;
@@ -761,12 +832,38 @@ g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *
                        header = next;
                }
        } else {
-               header = g_mime_header_new (name, value, -1);
+               header = g_mime_header_new (name, value, raw_value, offset);
                list_append (&headers->list, (ListNode *) header);
                g_hash_table_insert (headers->hash, header->name, header);
        }
+}
+
+
+/**
+ * g_mime_header_list_set:
+ * @headers: a #GMimeHeaderList
+ * @name: header name
+ * @value: header value
+ *
+ * Set the value of the specified header. If @value is %NULL and the
+ * header, @name, had not been previously set, a space will be set
+ * aside for it (useful for setting the order of headers before values
+ * can be obtained for them) otherwise the header will be unset.
+ *
+ * Note: If there are multiple headers with the specified field name,
+ * the first instance of the header will be replaced and further
+ * instances will be removed.
+ *
+ * Additionally, @value should be encoded with a function such as
+ * g_mime_utils_header_encode_text().
+ **/
+void
+g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value)
+{
+       g_return_if_fail (headers != NULL);
+       g_return_if_fail (name != NULL);
        
-       g_mime_header_list_set_stream (headers, NULL);
+       _g_mime_header_list_set (headers, name, value, NULL, -1);
 }
 
 
@@ -810,8 +907,6 @@ g_mime_header_list_remove (GMimeHeaderList *headers, const char *name)
        list_unlink ((ListNode *) header);
        g_mime_header_free (header);
        
-       g_mime_header_list_set_stream (headers, NULL);
-       
        return TRUE;
 }
 
@@ -870,20 +965,6 @@ g_mime_header_list_foreach (const GMimeHeaderList *headers, GMimeHeaderForeachFu
 }
 
 
-static ssize_t
-default_writer (GMimeStream *stream, const char *name, const char *value)
-{
-       ssize_t nwritten;
-       char *val;
-       
-       val = g_mime_utils_header_printf ("%s: %s\n", name, value);
-       nwritten = g_mime_stream_write_string (stream, val);
-       g_free (val);
-       
-       return nwritten;
-}
-
-
 /**
  * g_mime_header_list_write_to_stream:
  * @headers: a #GMimeHeaderList
@@ -897,31 +978,21 @@ ssize_t
 g_mime_header_list_write_to_stream (const GMimeHeaderList *headers, GMimeStream *stream)
 {
        ssize_t nwritten, total = 0;
-       GMimeHeaderWriter writer;
        GHashTable *writers;
        GMimeHeader *header;
+       char *val;
        
        g_return_val_if_fail (headers != NULL, -1);
        g_return_val_if_fail (stream != NULL, -1);
        
-       if (headers->stream) {
-               g_mime_stream_reset (headers->stream);
-               return g_mime_stream_write_to_stream (headers->stream, stream);
-       }
-       
        header = (GMimeHeader *) headers->list.head;
        writers = headers->writers;
        
        while (header->next) {
-               if (header->value) {
-                       if (!(writer = g_hash_table_lookup (writers, header->name)))
-                               writer = default_writer;
-                       
-                       if ((nwritten = writer (stream, header->name, header->value)) == -1)
-                               return -1;
-                       
-                       total += nwritten;
-               }
+               if ((nwritten = g_mime_header_write_to_stream (writers, header, stream)) == -1)
+                       return -1;
+               
+               total += nwritten;
                
                header = header->next;
        }
@@ -951,14 +1022,7 @@ g_mime_header_list_to_string (const GMimeHeaderList *headers)
        array = g_byte_array_new ();
        stream = g_mime_stream_mem_new ();
        g_mime_stream_mem_set_byte_array (GMIME_STREAM_MEM (stream), array);
-       
-       if (headers->stream) {
-               g_mime_stream_reset (headers->stream);
-               g_mime_stream_write_to_stream (headers->stream, stream);
-       } else {
-               g_mime_header_list_write_to_stream (headers, stream);
-       }
-       
+       g_mime_header_list_write_to_stream (headers, stream);
        g_object_unref (stream);
        
        g_byte_array_append (array, (unsigned char *) "", 1);
@@ -994,52 +1058,6 @@ g_mime_header_list_register_writer (GMimeHeaderList *headers, const char *name,
 }
 
 
-
-/**
- * g_mime_header_list_set_stream:
- * @headers: a #GMimeHeaderList
- * @stream: a #GMimeStream
- *
- * Set the raw header stream.
- **/
-void
-g_mime_header_list_set_stream (GMimeHeaderList *headers, GMimeStream *stream)
-{
-       g_return_if_fail (stream == NULL || GMIME_IS_STREAM (stream));
-       g_return_if_fail (headers != NULL);
-       
-       if (headers->stream == stream)
-               return;
-       
-       if (stream)
-               g_object_ref (stream);
-       
-       if (headers->stream)
-               g_object_unref (headers->stream);
-       
-       headers->stream = stream;
-       
-       g_mime_event_emit (headers->changed, NULL);
-}
-
-
-/**
- * g_mime_header_list_get_stream:
- * @headers: a #GMimeHeaderList
- *
- * Gets the raw stream representing @headers.
- *
- * Returns: (transfer none): a #GMimeStream if set or %NULL otherwise.
- **/
-GMimeStream *
-g_mime_header_list_get_stream (GMimeHeaderList *headers)
-{
-       g_return_val_if_fail (headers != NULL, NULL);
-       
-       return headers->stream;
-}
-
-
 GMimeEvent *
 _g_mime_header_list_get_changed_event (GMimeHeaderList *headers)
 {
diff --git a/gmime/gmime-header.h b/gmime/gmime-header.h
index 998f7c1..ce1ff8d 100644
--- a/gmime/gmime-header.h
+++ b/gmime/gmime-header.h
@@ -42,6 +42,14 @@ typedef void (* GMimeHeaderForeachFunc) (const char *name, const char *value, gp
 
 
 /**
+ * GMimeHeader:
+ *
+ * A message/rfc822 header.
+ **/
+typedef struct _GMimeHeader GMimeHeader;
+
+
+/**
  * GMimeHeaderList:
  *
  * A message or mime-part header.
@@ -83,13 +91,17 @@ gboolean g_mime_header_iter_last (GMimeHeaderIter *iter);
 gboolean g_mime_header_iter_next (GMimeHeaderIter *iter);
 gboolean g_mime_header_iter_prev (GMimeHeaderIter *iter);
 
-/*gint64 g_mime_header_iter_get_offset (GMimeHeaderIter *iter);*/
 const char *g_mime_header_iter_get_name (GMimeHeaderIter *iter);
+
 gboolean g_mime_header_iter_set_value (GMimeHeaderIter *iter, const char *value);
 const char *g_mime_header_iter_get_value (GMimeHeaderIter *iter);
 
+gint64 g_mime_header_iter_get_offset (GMimeHeaderIter *iter);
+
 gboolean g_mime_header_iter_remove (GMimeHeaderIter *iter);
 
+ssize_t g_mime_header_iter_write_to_stream (GMimeHeaderIter *iter, GMimeStream *stream);
+
 
 /**
  * GMimeHeaderWriter:
@@ -104,7 +116,6 @@ gboolean g_mime_header_iter_remove (GMimeHeaderIter *iter);
  **/
 typedef ssize_t (* GMimeHeaderWriter) (GMimeStream *stream, const char *name, const char *value);
 
-
 GMimeHeaderList *g_mime_header_list_new (void);
 
 void g_mime_header_list_destroy (GMimeHeaderList *headers);
diff --git a/gmime/gmime-message-part.c b/gmime/gmime-message-part.c
index 33fe7e4..78cdcc5 100644
--- a/gmime/gmime-message-part.c
+++ b/gmime/gmime-message-part.c
@@ -47,7 +47,7 @@ static void g_mime_message_part_init (GMimeMessagePart *message_part, GMimeMessa
 static void g_mime_message_part_finalize (GObject *object);
 
 /* GMimeObject class methods */
-static ssize_t message_part_write_to_stream (GMimeObject *object, GMimeStream *stream);
+static ssize_t message_part_write_to_stream (GMimeObject *object, GMimeStream *stream, gboolean 
content_only);
 
 
 static GMimeObjectClass *parent_class = NULL;
@@ -109,22 +109,24 @@ g_mime_message_part_finalize (GObject *object)
 }
 
 static ssize_t
-message_part_write_to_stream (GMimeObject *object, GMimeStream *stream)
+message_part_write_to_stream (GMimeObject *object, GMimeStream *stream, gboolean content_only)
 {
        GMimeMessagePart *part = (GMimeMessagePart *) object;
        ssize_t nwritten, total = 0;
        
-       /* write the content headers */
-       if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1)
-               return -1;
-       
-       total += nwritten;
-       
-       /* terminate the headers */
-       if ((nwritten = g_mime_stream_write (stream, "\n", 1)) == -1)
-               return -1;
-       
-       total += nwritten;
+       if (!content_only) {
+               /* write the content headers */
+               if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1)
+                       return -1;
+               
+               total += nwritten;
+               
+               /* terminate the headers */
+               if ((nwritten = g_mime_stream_write (stream, "\n", 1)) == -1)
+                       return -1;
+               
+               total += nwritten;
+       }
        
        /* write the message */
        if (part->message) {
diff --git a/gmime/gmime-message-partial.c b/gmime/gmime-message-partial.c
index 165012e..098a8cf 100644
--- a/gmime/gmime-message-partial.c
+++ b/gmime/gmime-message-partial.c
@@ -41,6 +41,10 @@
  * A #GMimeMessagePartial represents the message/partial MIME part.
  **/
 
+extern const char *_g_mime_header_iter_get_raw_value (GMimeHeaderIter *iter);
+
+extern void _g_mime_object_append_header (GMimeObject *object, const char *header, const char *value, const 
char *raw_value, gint64 offset);
+
 
 /* GObject class methods */
 static void g_mime_message_partial_class_init (GMimeMessagePartialClass *klass);
@@ -48,9 +52,9 @@ static void g_mime_message_partial_init (GMimeMessagePartial *catpart, GMimeMess
 static void g_mime_message_partial_finalize (GObject *object);
 
 /* GMimeObject class methods */
-static void message_partial_prepend_header (GMimeObject *object, const char *header, const char *value);
-static void message_partial_append_header (GMimeObject *object, const char *header, const char *value);
-static void message_partial_set_header (GMimeObject *object, const char *header, const char *value);
+static void message_partial_prepend_header (GMimeObject *object, const char *header, const char *value, 
const char *raw_value, gint64 offset);
+static void message_partial_append_header (GMimeObject *object, const char *header, const char *value, const 
char *raw_value, gint64 offset);
+static void message_partial_set_header (GMimeObject *object, const char *header, const char *value, const 
char *raw_value, gint64 offset);
 static const char *message_partial_get_header (GMimeObject *object, const char *header);
 static gboolean message_partial_remove_header (GMimeObject *object, const char *header);
 static void message_partial_set_content_type (GMimeObject *object, GMimeContentType *content_type);
@@ -121,33 +125,33 @@ g_mime_message_partial_finalize (GObject *object)
 }
 
 static void
-message_partial_prepend_header (GMimeObject *object, const char *header, const char *value)
+message_partial_prepend_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset)
 {
        /* RFC 1864 states that you cannot set a Content-MD5 on a message part */
        if (!g_ascii_strcasecmp ("Content-MD5", header))
                return;
        
-       GMIME_OBJECT_CLASS (parent_class)->prepend_header (object, header, value);
+       GMIME_OBJECT_CLASS (parent_class)->prepend_header (object, header, value, raw_value, offset);
 }
 
 static void
-message_partial_append_header (GMimeObject *object, const char *header, const char *value)
+message_partial_append_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset)
 {
        /* RFC 1864 states that you cannot set a Content-MD5 on a message part */
        if (!g_ascii_strcasecmp ("Content-MD5", header))
                return;
        
-       GMIME_OBJECT_CLASS (parent_class)->append_header (object, header, value);
+       GMIME_OBJECT_CLASS (parent_class)->append_header (object, header, value, raw_value, offset);
 }
 
 static void
-message_partial_set_header (GMimeObject *object, const char *header, const char *value)
+message_partial_set_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset)
 {
        /* RFC 1864 states that you cannot set a Content-MD5 on a message part */
        if (!g_ascii_strcasecmp ("Content-MD5", header))
                return;
        
-       GMIME_OBJECT_CLASS (parent_class)->set_header (object, header, value);
+       GMIME_OBJECT_CLASS (parent_class)->set_header (object, header, value, raw_value, offset);
 }
 
 static const char *
@@ -372,10 +376,11 @@ g_mime_message_partial_reconstruct_message (GMimeMessagePartial **partials, size
 static GMimeMessage *
 message_partial_message_new (GMimeMessage *base)
 {
-       const char *name, *value;
+       const char *name, *value, *raw_value;
        GMimeMessage *message;
        GMimeHeaderList *list;
        GMimeHeaderIter iter;
+       gint64 offset;
        
        message = g_mime_message_new (FALSE);
        
@@ -385,7 +390,10 @@ message_partial_message_new (GMimeMessage *base)
                do {
                        name = g_mime_header_iter_get_name (&iter);
                        value = g_mime_header_iter_get_value (&iter);
-                       g_mime_object_append_header ((GMimeObject *) message, name, value);
+                       raw_value = _g_mime_header_iter_get_raw_value (&iter);
+                       offset = g_mime_header_iter_get_offset (&iter);
+                       
+                       _g_mime_object_append_header ((GMimeObject *) message, name, value, raw_value, 
offset);
                } while (g_mime_header_iter_next (&iter));
        }
        
diff --git a/gmime/gmime-message.c b/gmime/gmime-message.c
index f121b93..cec1fbe 100644
--- a/gmime/gmime-message.c
+++ b/gmime/gmime-message.c
@@ -49,6 +49,16 @@
  * A #GMimeMessage represents an rfc822 message.
  **/
 
+extern void _g_mime_object_prepend_header (GMimeObject *object, const char *header, const char *value, const 
char *raw_value, gint64 offset);
+extern void _g_mime_object_append_header (GMimeObject *object, const char *header, const char *value, const 
char *raw_value, gint64 offset);
+extern void _g_mime_object_set_header (GMimeObject *object, const char *header, const char *value, const 
char *raw_value, gint64 offset);
+
+extern void _g_mime_header_iter_set_offset (GMimeHeaderIter *iter, gint64 offset);
+
+extern void _g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char *value, 
const char *raw_value, gint64 offset);
+extern void _g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char *value, const 
char *raw_value, gint64 offset);
+extern void _g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value, const 
char *raw_value, gint64 offset);
+
 extern GMimeEvent *_g_mime_header_list_get_changed_event (GMimeHeaderList *headers);
 extern char *_g_mime_utils_unstructured_header_fold (const char *field, const char *value);
 extern char *_g_mime_utils_structured_header_fold (const char *field, const char *value);
@@ -58,13 +68,13 @@ static void g_mime_message_init (GMimeMessage *message, GMimeMessageClass *klass
 static void g_mime_message_finalize (GObject *object);
 
 /* GMimeObject class methods */
-static void message_prepend_header (GMimeObject *object, const char *header, const char *value);
-static void message_append_header (GMimeObject *object, const char *header, const char *value);
-static void message_set_header (GMimeObject *object, const char *header, const char *value);
+static void message_prepend_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset);
+static void message_append_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset);
+static void message_set_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset);
 static const char *message_get_header (GMimeObject *object, const char *header);
 static gboolean message_remove_header (GMimeObject *object, const char *header);
 static char *message_get_headers (GMimeObject *object);
-static ssize_t message_write_to_stream (GMimeObject *object, GMimeStream *stream);
+static ssize_t message_write_to_stream (GMimeObject *object, GMimeStream *stream, gboolean content_only);
 static void message_encode (GMimeObject *object, GMimeEncodingConstraint constraint);
 
 /*static ssize_t write_structured (GMimeStream *stream, const char *name, const char *value);*/
@@ -152,13 +162,6 @@ g_mime_message_class_init (GMimeMessageClass *klass)
 }
 
 static void
-mime_part_headers_changed (GMimeHeaderList *headers, gpointer args, GMimeMessage *message)
-{
-       /* clear the message's header stream */
-       g_mime_header_list_set_stream (((GMimeObject *) message)->headers, NULL);
-}
-
-static void
 connect_changed_event (GMimeMessage *message, GMimeRecipientType type)
 {
        InternetAddressList *list;
@@ -241,7 +244,6 @@ static void
 g_mime_message_finalize (GObject *object)
 {
        GMimeMessage *message = (GMimeMessage *) object;
-       GMimeEvent *changed;
        guint i;
        
        g_free (message->from);
@@ -260,11 +262,8 @@ g_mime_message_finalize (GObject *object)
        g_free (message->message_id);
        
        /* unref child mime part */
-       if (message->mime_part) {
-               changed = _g_mime_header_list_get_changed_event (message->mime_part->headers);
-               g_mime_event_remove (changed, (GMimeEventCallback) mime_part_headers_changed, message);
+       if (message->mime_part)
                g_object_unref (message->mime_part);
-       }
        
        G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -759,7 +758,7 @@ message_add_recipients_from_string (GMimeMessage *message, int action, GMimeReci
 static gboolean
 process_header (GMimeObject *object, int action, const char *header, const char *value)
 {
-       GMimeMessage *message = (GMimeMessage *) object;        
+       GMimeMessage *message = (GMimeMessage *) object;
        InternetAddressList *addrlist;
        time_t date;
        int offset;
@@ -829,66 +828,57 @@ process_header (GMimeObject *object, int action, const char *header, const char
 }
 
 static void
-message_prepend_header (GMimeObject *object, const char *header, const char *value)
+message_prepend_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, 
gint64 offset)
 {
        GMimeMessage *message = (GMimeMessage *) object;
        
        /* Content-* headers don't belong on the message, they belong on the part. */
        if (!g_ascii_strncasecmp ("Content-", header, 8)) {
                if (message->mime_part)
-                       g_mime_object_prepend_header (message->mime_part, header, value);
+                       _g_mime_object_prepend_header (message->mime_part, header, value, raw_value, offset);
                return;
        }
        
        if (!process_header (object, PREPEND, header, value))
-               GMIME_OBJECT_CLASS (parent_class)->prepend_header (object, header, value);
+               GMIME_OBJECT_CLASS (parent_class)->prepend_header (object, header, value, raw_value, offset);
        else
-               g_mime_header_list_prepend (object->headers, header, value);
-       
-       if (message->mime_part)
-               g_mime_header_list_set_stream (message->mime_part->headers, NULL);
+               _g_mime_header_list_prepend (object->headers, header, value, raw_value, offset);
 }
 
 static void
-message_append_header (GMimeObject *object, const char *header, const char *value)
+message_append_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, 
gint64 offset)
 {
        GMimeMessage *message = (GMimeMessage *) object;
        
        /* Content-* headers don't belong on the message, they belong on the part. */
        if (!g_ascii_strncasecmp ("Content-", header, 8)) {
                if (message->mime_part)
-                       g_mime_object_append_header (message->mime_part, header, value);
+                       _g_mime_object_append_header (message->mime_part, header, value, raw_value, offset);
                return;
        }
        
        if (!process_header (object, APPEND, header, value))
-               GMIME_OBJECT_CLASS (parent_class)->append_header (object, header, value);
+               GMIME_OBJECT_CLASS (parent_class)->append_header (object, header, value, raw_value, offset);
        else
-               g_mime_header_list_append (object->headers, header, value);
-       
-       if (message->mime_part)
-               g_mime_header_list_set_stream (message->mime_part->headers, NULL);
+               _g_mime_header_list_append (object->headers, header, value, raw_value, offset);
 }
 
 static void
-message_set_header (GMimeObject *object, const char *header, const char *value)
+message_set_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, 
gint64 offset)
 {
        GMimeMessage *message = (GMimeMessage *) object;
        
        /* Content-* headers don't belong on the message, they belong on the part. */
        if (!g_ascii_strncasecmp ("Content-", header, 8)) {
                if (message->mime_part)
-                       g_mime_object_set_header (message->mime_part, header, value);
+                       _g_mime_object_set_header (message->mime_part, header, value, raw_value, offset);
                return;
        }
        
        if (!process_header (object, SET, header, value))
-               GMIME_OBJECT_CLASS (parent_class)->set_header (object, header, value);
+               GMIME_OBJECT_CLASS (parent_class)->set_header (object, header, value, raw_value, offset);
        else
-               g_mime_header_list_set (object->headers, header, value);
-       
-       if (message->mime_part)
-               g_mime_header_list_set_stream (message->mime_part->headers, NULL);
+               _g_mime_header_list_set (object->headers, header, value, raw_value, offset);
 }
 
 static const char *
@@ -978,21 +968,79 @@ message_remove_header (GMimeObject *object, const char *header)
                break;
        }
        
-       if (GMIME_OBJECT_CLASS (parent_class)->remove_header (object, header)) {
-               if (message->mime_part)
-                       g_mime_header_list_set_stream (message->mime_part->headers, NULL);
+       return GMIME_OBJECT_CLASS (parent_class)->remove_header (object, header);
+}
+
+
+static ssize_t
+write_headers_to_stream (GMimeObject *object, GMimeStream *stream)
+{
+       GMimeMessage *message = (GMimeMessage *) object;
+       GMimeObject *mime_part = message->mime_part;
+       ssize_t nwritten, total = 0;
+       GMimeHeaderIter mesg, body;
+       
+       if (!g_mime_header_list_get_iter (object->headers, &mesg))
+               return -1;
+       
+       if (message->mime_part && g_mime_header_list_get_iter (mime_part->headers, &body)) {
+               while (g_mime_header_iter_is_valid (&mesg) && g_mime_header_iter_is_valid (&body)) {
+                       gint64 mesg_offset, body_offset;
+                       
+                       if ((body_offset = g_mime_header_iter_get_offset (&body)) < 0)
+                               break;
+                       
+                       mesg_offset = g_mime_header_iter_get_offset (&mesg);
+                       
+                       if (mesg_offset >= 0 && mesg_offset < body_offset) {
+                               if ((nwritten = g_mime_header_iter_write_to_stream (&mesg, stream)) == -1)
+                                       return -1;
+                               
+                               total += nwritten;
+                               
+                               if (!g_mime_header_iter_next (&mesg))
+                                       break;
+                       } else {
+                               if ((nwritten = g_mime_header_iter_write_to_stream (&body, stream)) == -1)
+                                       return -1;
+                               
+                               total += nwritten;
+                               
+                               if (!g_mime_header_iter_next (&body))
+                                       break;
+                       }
+               }
                
-               return TRUE;
+               while (g_mime_header_iter_is_valid (&mesg)) {
+                       if ((nwritten = g_mime_header_iter_write_to_stream (&mesg, stream)) == -1)
+                               return -1;
+                       
+                       total += nwritten;
+                       
+                       if (!g_mime_header_iter_next (&mesg))
+                               break;
+               }
+               
+               while (g_mime_header_iter_is_valid (&body)) {
+                       if ((nwritten = g_mime_header_iter_write_to_stream (&body, stream)) == -1)
+                               return -1;
+                       
+                       total += nwritten;
+                       
+                       if (!g_mime_header_iter_next (&body))
+                               break;
+               }
+               
+               return total;
        }
        
-       return FALSE;
+       return g_mime_header_list_write_to_stream (object->headers, stream);
 }
 
 
 static char *
 message_get_headers (GMimeObject *object)
 {
-       GMimeMessage *message = (GMimeMessage *) object;
        GMimeStream *stream;
        GByteArray *ba;
        char *str;
@@ -1000,20 +1048,7 @@ message_get_headers (GMimeObject *object)
        ba = g_byte_array_new ();
        stream = g_mime_stream_mem_new ();
        g_mime_stream_mem_set_byte_array (GMIME_STREAM_MEM (stream), ba);
-       
-       if (message->mime_part && g_mime_header_list_get_stream (message->mime_part->headers)) {
-               /* if the mime part has raw headers, then it contains the message headers as well */
-               g_mime_header_list_write_to_stream (message->mime_part->headers, stream);
-       } else {
-               g_mime_header_list_write_to_stream (object->headers, stream);
-               if (message->mime_part) {
-                       if (g_mime_object_get_header (message->mime_part, "Content-Type") &&
-                           !g_mime_header_list_get (object->headers, "MIME-Version"))
-                               g_mime_stream_write_string (stream, "MIME-Version: 1.0\n");
-                       g_mime_header_list_write_to_stream (message->mime_part->headers, stream);
-               }
-       }
-       
+       write_headers_to_stream (object, stream);
        g_object_unref (stream);
        g_byte_array_append (ba, (unsigned char *) "", 1);
        str = (char *) ba->data;
@@ -1023,39 +1058,29 @@ message_get_headers (GMimeObject *object)
 }
 
 static ssize_t
-message_write_to_stream (GMimeObject *object, GMimeStream *stream)
+message_write_to_stream (GMimeObject *object, GMimeStream *stream, gboolean content_only)
 {
        GMimeMessage *message = (GMimeMessage *) object;
        ssize_t nwritten, total = 0;
        
-       if (message->mime_part) {
-               if (!g_mime_header_list_get_stream (message->mime_part->headers)) {
-                       if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1)
-                               return -1;
-                       
-                       total += nwritten;
-                       
-                       if (!g_mime_header_list_get (object->headers, "MIME-Version")) {
-                               if ((nwritten = g_mime_stream_write_string (stream, "MIME-Version: 1.0\n")) 
== -1)
-                                       return -1;
-                               
-                               total += nwritten;
-                       }
-               }
-               
-               if ((nwritten = g_mime_object_write_to_stream (message->mime_part, stream)) == -1)
-                       return -1;
-       } else {
-               if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1)
+       if (!content_only) {
+               if ((nwritten = write_headers_to_stream (object, stream)) == -1)
                        return -1;
                
                total += nwritten;
                
                if ((nwritten = g_mime_stream_write (stream, "\n", 1)) == -1)
                        return -1;
+               
+               total += nwritten;
        }
        
-       total += nwritten;
+       if (message->mime_part) {
+               if ((nwritten = GMIME_OBJECT_GET_CLASS (object)->write_to_stream (message->mime_part, stream, 
TRUE)) == -1)
+                       return -1;
+               
+               total += nwritten;
+       }
        
        return total;
 }
@@ -1135,9 +1160,6 @@ g_mime_message_set_sender (GMimeMessage *message, const char *sender)
                g_mime_header_list_set (GMIME_OBJECT (message)->headers, "From", "");
                message->from = NULL;
        }
-       
-       if (message->mime_part)
-               g_mime_header_list_set_stream (message->mime_part->headers, NULL);
 }
 
 
@@ -1192,9 +1214,6 @@ g_mime_message_set_reply_to (GMimeMessage *message, const char *reply_to)
                g_mime_header_list_set (GMIME_OBJECT (message)->headers, "Reply-To", "");
                message->reply_to = NULL;
        }
-       
-       if (message->mime_part)
-               g_mime_header_list_set_stream (message->mime_part->headers, NULL);
 }
 
 
@@ -1234,9 +1253,6 @@ sync_recipient_header (GMimeMessage *message, GMimeRecipientType type)
                /* list should never be NULL... */
                g_mime_header_list_set (object->headers, name, NULL);
        }
-       
-       if (message->mime_part)
-               g_mime_header_list_set_stream (message->mime_part->headers, NULL);
 }
 
 static void
@@ -1283,11 +1299,6 @@ g_mime_message_add_recipient (GMimeMessage *message, GMimeRecipientType type, co
        ia = internet_address_mailbox_new (name, addr);
        internet_address_list_add (recipients, ia);
        g_object_unref (ia);
-       
-       if (message->mime_part)
-               g_mime_header_list_set_stream (message->mime_part->headers, NULL);
-       
-       g_mime_header_list_set_stream (((GMimeObject *) message)->headers, NULL);
 }
 
 
@@ -1368,9 +1379,6 @@ g_mime_message_set_subject (GMimeMessage *message, const char *subject)
        encoded = g_mime_utils_header_encode_text (message->subject);
        g_mime_object_set_header (GMIME_OBJECT (message), "Subject", encoded);
        g_free (encoded);
-       
-       if (message->mime_part)
-               g_mime_header_list_set_stream (message->mime_part->headers, NULL);
 }
 
 
@@ -1414,9 +1422,6 @@ g_mime_message_set_date (GMimeMessage *message, time_t date, int tz_offset)
        str = g_mime_utils_header_format_date (date, tz_offset);
        g_mime_object_set_header (GMIME_OBJECT (message), "Date", str);
        g_free (str);
-       
-       if (message->mime_part)
-               g_mime_header_list_set_stream (message->mime_part->headers, NULL);
 }
 
 
@@ -1483,9 +1488,6 @@ g_mime_message_set_date_as_string (GMimeMessage *message, const char *str)
        buf = g_mime_utils_header_format_date (date, tz_offset);
        g_mime_object_set_header (GMIME_OBJECT (message), "Date", buf);
        g_free (buf);
-       
-       if (message->mime_part)
-               g_mime_header_list_set_stream (message->mime_part->headers, NULL);
 }
 
 
@@ -1510,9 +1512,6 @@ g_mime_message_set_message_id (GMimeMessage *message, const char *message_id)
        msgid = g_strdup_printf ("<%s>", message_id);
        g_mime_object_set_header (GMIME_OBJECT (message), "Message-Id", msgid);
        g_free (msgid);
-       
-       if (message->mime_part)
-               g_mime_header_list_set_stream (message->mime_part->headers, NULL);
 }
 
 
@@ -1563,7 +1562,7 @@ g_mime_message_get_mime_part (GMimeMessage *message)
 void
 g_mime_message_set_mime_part (GMimeMessage *message, GMimeObject *mime_part)
 {
-       GMimeEvent *changed;
+       GMimeHeaderIter iter;
        
        g_return_if_fail (mime_part == NULL || GMIME_IS_OBJECT (mime_part));
        g_return_if_fail (GMIME_IS_MESSAGE (message));
@@ -1571,23 +1570,24 @@ g_mime_message_set_mime_part (GMimeMessage *message, GMimeObject *mime_part)
        if (message->mime_part == mime_part)
                return;
        
-       if (message->mime_part) {
-               changed = _g_mime_header_list_get_changed_event (message->mime_part->headers);
-               g_mime_event_remove (changed, (GMimeEventCallback) mime_part_headers_changed, message);
-               
-               g_mime_header_list_set_stream (message->mime_part->headers, NULL);
+       if (message->mime_part)
                g_object_unref (message->mime_part);
-       }
        
        if (mime_part) {
-               changed = _g_mime_header_list_get_changed_event (mime_part->headers);
-               g_mime_header_list_set_stream (mime_part->headers, NULL);
-               g_mime_event_add (changed, (GMimeEventCallback) mime_part_headers_changed, message);
+               GMimeHeaderList *headers = ((GMimeObject *) message)->headers;
+               
+               if (!g_mime_header_list_contains (headers, "MIME-Version"))
+                       g_mime_header_list_append (headers, "MIME-Version", "1.0");
+               
+               if (g_mime_header_list_get_iter (mime_part->headers, &iter)) {
+                       do {
+                               _g_mime_header_iter_set_offset (&iter, -1);
+                       } while (g_mime_header_iter_next (&iter));
+               }
+               
                g_object_ref (mime_part);
        }
        
-       g_mime_header_list_set_stream (((GMimeObject *) message)->headers, NULL);
-       
        message->mime_part = mime_part;
 }
 
diff --git a/gmime/gmime-multipart.c b/gmime/gmime-multipart.c
index b17197e..a1121a4 100644
--- a/gmime/gmime-multipart.c
+++ b/gmime/gmime-multipart.c
@@ -49,13 +49,16 @@
  **/
 
 
+extern gboolean _g_mime_header_list_has_raw_value (const GMimeHeaderList *headers, const char *name);
+
+
 /* GObject class methods */
 static void g_mime_multipart_class_init (GMimeMultipartClass *klass);
 static void g_mime_multipart_init (GMimeMultipart *multipart, GMimeMultipartClass *klass);
 static void g_mime_multipart_finalize (GObject *object);
 
 /* GMimeObject class methods */
-static ssize_t multipart_write_to_stream (GMimeObject *object, GMimeStream *stream);
+static ssize_t multipart_write_to_stream (GMimeObject *object, GMimeStream *stream, gboolean content_only);
 static void multipart_encode (GMimeObject *object, GMimeEncodingConstraint constraint);
 
 /* GMimeMultipart class methods */
@@ -152,7 +155,7 @@ g_mime_multipart_finalize (GObject *object)
 }
 
 static ssize_t
-multipart_write_to_stream (GMimeObject *object, GMimeStream *stream)
+multipart_write_to_stream (GMimeObject *object, GMimeStream *stream, gboolean content_only)
 {
        GMimeMultipart *multipart = (GMimeMultipart *) object;
        ssize_t nwritten, total = 0;
@@ -160,30 +163,24 @@ multipart_write_to_stream (GMimeObject *object, GMimeStream *stream)
        GMimeObject *part;
        guint i;
        
-       /* make sure a boundary is set unless we are writing out a raw
-        * header (in which case it should already be set... or if
-        * not, then it's a broken multipart and so we don't want to
-        * alter it or we'll completely break the output) */
        boundary = g_mime_object_get_content_type_parameter (object, "boundary");
-       if (!boundary && !g_mime_header_list_get_stream (object->headers)) {
-               g_mime_multipart_set_boundary (multipart, NULL);
-               boundary = g_mime_object_get_content_type_parameter (object, "boundary");
-       }
-       
-       /* write the content headers */
-       if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1)
-               return -1;
-       
-       total += nwritten;
        
-       /* write the preface */
-       if (multipart->preface) {
+       if (!content_only) {
+               /* write the content headers */
+               if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1)
+                       return -1;
+               
+               total += nwritten;
+               
                /* terminate the headers */
                if (g_mime_stream_write (stream, "\n", 1) == -1)
                        return -1;
                
                total++;
-               
+       }
+       
+       /* write the preface */
+       if (multipart->preface) {
                if ((nwritten = g_mime_stream_write_string (stream, multipart->preface)) == -1)
                        return -1;
                
@@ -260,6 +257,8 @@ g_mime_multipart_new (void)
        g_mime_object_set_content_type (GMIME_OBJECT (multipart), content_type);
        g_object_unref (content_type);
        
+       g_mime_multipart_set_boundary (multipart, NULL);
+       
        return multipart;
 }
 
@@ -286,6 +285,8 @@ g_mime_multipart_new_with_subtype (const char *subtype)
        g_mime_object_set_content_type (GMIME_OBJECT (multipart), content_type);
        g_object_unref (content_type);
        
+       g_mime_multipart_set_boundary (multipart, NULL);
+       
        return multipart;
 }
 
diff --git a/gmime/gmime-object.c b/gmime/gmime-object.c
index ca65923..beacbd2 100644
--- a/gmime/gmime-object.c
+++ b/gmime/gmime-object.c
@@ -55,6 +55,10 @@ struct _subtype_bucket {
        GType object_type;
 };
 
+extern void _g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char *value, 
const char *raw_value, gint64 offset);
+extern void _g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char *value, const 
char *raw_value, gint64 offset);
+extern void _g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value, const 
char *raw_value, gint64 offset);
+
 static void _g_mime_object_set_content_disposition (GMimeObject *object, GMimeContentDisposition 
*disposition);
 void _g_mime_object_set_content_type (GMimeObject *object, GMimeContentType *content_type);
 
@@ -62,14 +66,14 @@ static void g_mime_object_class_init (GMimeObjectClass *klass);
 static void g_mime_object_init (GMimeObject *object, GMimeObjectClass *klass);
 static void g_mime_object_finalize (GObject *object);
 
-static void object_prepend_header (GMimeObject *object, const char *name, const char *value);
-static void object_append_header (GMimeObject *object, const char *name, const char *value);
-static void object_set_header (GMimeObject *object, const char *name, const char *value);
+static void object_prepend_header (GMimeObject *object, const char *name, const char *value, const char 
*raw_value, gint64 offset);
+static void object_append_header (GMimeObject *object, const char *name, const char *value, const char 
*raw_value, gint64 offset);
+static void object_set_header (GMimeObject *object, const char *name, const char *value, const char 
*raw_value, gint64 offset);
 static const char *object_get_header (GMimeObject *object, const char *name);
 static gboolean object_remove_header (GMimeObject *object, const char *name);
 static void object_set_content_type (GMimeObject *object, GMimeContentType *content_type);
 static char *object_get_headers (GMimeObject *object);
-static ssize_t object_write_to_stream (GMimeObject *object, GMimeStream *stream);
+static ssize_t object_write_to_stream (GMimeObject *object, GMimeStream *stream, gboolean content_only);
 static void object_encode (GMimeObject *object, GMimeEncodingConstraint constraint);
 
 static ssize_t write_content_type (GMimeStream *stream, const char *name, const char *value);
@@ -733,7 +737,7 @@ static char *content_headers[] = {
 };
 
 static gboolean
-process_header (GMimeObject *object, const char *header, const char *value)
+process_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, gint64 
offset)
 {
        GMimeContentDisposition *disposition;
        GMimeContentType *content_type;
@@ -766,16 +770,23 @@ process_header (GMimeObject *object, const char *header, const char *value)
                return FALSE;
        }
        
-       g_mime_header_list_set (object->headers, header, value);
+       _g_mime_header_list_set (object->headers, header, value, raw_value, offset);
        
        return TRUE;
 }
 
 static void
-object_prepend_header (GMimeObject *object, const char *header, const char *value)
+object_prepend_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, 
gint64 offset)
+{
+       if (!process_header (object, header, value, raw_value, offset))
+               _g_mime_header_list_prepend (object->headers, header, value, raw_value, offset);
+}
+
+
+void
+_g_mime_object_prepend_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset)
 {
-       if (!process_header (object, header, value))
-               g_mime_header_list_prepend (object->headers, header, value);
+       GMIME_OBJECT_GET_CLASS (object)->prepend_header (object, header, value, raw_value, offset);
 }
 
 
@@ -784,6 +795,8 @@ object_prepend_header (GMimeObject *object, const char *header, const char *valu
  * @object: a #GMimeObject
  * @header: header name
  * @value: header value
+ * @raw_value: raw header value
+ * @offset: header offset
  *
  * Prepends a raw, unprocessed header to the MIME object.
  *
@@ -797,14 +810,21 @@ g_mime_object_prepend_header (GMimeObject *object, const char *header, const cha
        g_return_if_fail (header != NULL);
        g_return_if_fail (value != NULL);
        
-       GMIME_OBJECT_GET_CLASS (object)->prepend_header (object, header, value);
+       GMIME_OBJECT_GET_CLASS (object)->prepend_header (object, header, value, NULL, 0);
 }
 
 static void
-object_append_header (GMimeObject *object, const char *header, const char *value)
+object_append_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, 
gint64 offset)
+{
+       if (!process_header (object, header, value, raw_value, offset))
+               _g_mime_header_list_append (object->headers, header, value, raw_value, offset);
+}
+
+
+void
+_g_mime_object_append_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset)
 {
-       if (!process_header (object, header, value))
-               g_mime_header_list_append (object->headers, header, value);
+       GMIME_OBJECT_GET_CLASS (object)->append_header (object, header, value, raw_value, offset);
 }
 
 
@@ -826,15 +846,22 @@ g_mime_object_append_header (GMimeObject *object, const char *header, const char
        g_return_if_fail (header != NULL);
        g_return_if_fail (value != NULL);
        
-       GMIME_OBJECT_GET_CLASS (object)->append_header (object, header, value);
+       GMIME_OBJECT_GET_CLASS (object)->append_header (object, header, value, NULL, 0);
 }
 
 
 static void
-object_set_header (GMimeObject *object, const char *header, const char *value)
+object_set_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, gint64 
offset)
+{
+       if (!process_header (object, header, value, raw_value, offset))
+               _g_mime_header_list_set (object->headers, header, value, raw_value, offset);
+}
+
+
+void
+_g_mime_object_set_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset)
 {
-       if (!process_header (object, header, value))
-               g_mime_header_list_set (object->headers, header, value);
+       GMIME_OBJECT_GET_CLASS (object)->set_header (object, header, value, raw_value, offset);
 }
 
 
@@ -856,7 +883,7 @@ g_mime_object_set_header (GMimeObject *object, const char *header, const char *v
        g_return_if_fail (header != NULL);
        g_return_if_fail (value != NULL);
        
-       GMIME_OBJECT_GET_CLASS (object)->set_header (object, header, value);
+       GMIME_OBJECT_GET_CLASS (object)->set_header (object, header, value, NULL, 0);
 }
 
 
@@ -971,7 +998,7 @@ g_mime_object_get_headers (GMimeObject *object)
 
 
 static ssize_t
-object_write_to_stream (GMimeObject *object, GMimeStream *stream)
+object_write_to_stream (GMimeObject *object, GMimeStream *stream, gboolean content_only)
 {
        return -1;
 }
@@ -992,7 +1019,7 @@ g_mime_object_write_to_stream (GMimeObject *object, GMimeStream *stream)
        g_return_val_if_fail (GMIME_IS_OBJECT (object), -1);
        g_return_val_if_fail (GMIME_IS_STREAM (stream), -1);
        
-       return GMIME_OBJECT_GET_CLASS (object)->write_to_stream (object, stream);
+       return GMIME_OBJECT_GET_CLASS (object)->write_to_stream (object, stream, FALSE);
 }
 
 
diff --git a/gmime/gmime-object.h b/gmime/gmime-object.h
index 10d1576..d49c947 100644
--- a/gmime/gmime-object.h
+++ b/gmime/gmime-object.h
@@ -66,9 +66,9 @@ struct _GMimeObject {
 struct _GMimeObjectClass {
        GObjectClass parent_class;
        
-       void         (* prepend_header) (GMimeObject *object, const char *header, const char *value);
-       void         (* append_header)  (GMimeObject *object, const char *header, const char *value);
-       void         (* set_header)     (GMimeObject *object, const char *header, const char *value);
+       void         (* prepend_header) (GMimeObject *object, const char *header, const char *value, const 
char *raw_value, gint64 offset);
+       void         (* append_header)  (GMimeObject *object, const char *header, const char *value, const 
char *raw_value, gint64 offset);
+       void         (* set_header)     (GMimeObject *object, const char *header, const char *value, const 
char *raw_value, gint64 offset);
        const char * (* get_header)     (GMimeObject *object, const char *header);
        gboolean     (* remove_header)  (GMimeObject *object, const char *header);
        
@@ -76,7 +76,7 @@ struct _GMimeObjectClass {
        
        char *       (* get_headers)   (GMimeObject *object);
        
-       ssize_t      (* write_to_stream) (GMimeObject *object, GMimeStream *stream);
+       ssize_t      (* write_to_stream) (GMimeObject *object, GMimeStream *stream, gboolean content_only);
        
        void         (* encode) (GMimeObject *object, GMimeEncodingConstraint constraint);
 };
diff --git a/gmime/gmime-parser.c b/gmime/gmime-parser.c
index 2cff709..e0e3c5e 100644
--- a/gmime/gmime-parser.c
+++ b/gmime/gmime-parser.c
@@ -74,7 +74,7 @@ typedef struct _boundary_stack {
 
 typedef struct _header_raw {
        struct _header_raw *next;
-       char *name, *value;
+       char *name, *value, *raw_value;
        gint64 offset;
 } HeaderRaw;
 
@@ -83,6 +83,7 @@ typedef struct _content_type {
        gboolean exists;
 } ContentType;
 
+extern void _g_mime_object_append_header (GMimeObject *object, const char *header, const char *value, const 
char *raw_value, gint64 offset);
 extern void _g_mime_object_set_content_type (GMimeObject *object, GMimeContentType *content_type);
 
 static void g_mime_parser_class_init (GMimeParserClass *klass);
@@ -367,15 +368,9 @@ parser_init (GMimeParser *parser, GMimeStream *stream)
        priv->headerleft = HEADER_INIT_SIZE - 1;
        priv->headerptr = priv->headerbuf;
        
-       if (offset == -1 || !priv->persist_stream) {
-               priv->rawbuf = g_malloc (HEADER_RAW_INIT_SIZE);
-               priv->rawleft = HEADER_RAW_INIT_SIZE - 1;
-               priv->rawptr = priv->rawbuf;
-       } else {
-               priv->rawbuf = NULL;
-               priv->rawptr = NULL;
-               priv->rawleft = 0;
-       }
+       priv->rawbuf = g_malloc (HEADER_RAW_INIT_SIZE);
+       priv->rawleft = HEADER_RAW_INIT_SIZE - 1;
+       priv->rawptr = priv->rawbuf;
        
        priv->message_headers_begin = -1;
        priv->message_headers_end = -1;
@@ -520,33 +515,9 @@ g_mime_parser_get_persist_stream (GMimeParser *parser)
 void
 g_mime_parser_set_persist_stream (GMimeParser *parser, gboolean persist)
 {
-       struct _GMimeParserPrivate *priv;
-       
        g_return_if_fail (GMIME_IS_PARSER (parser));
        
-       priv = parser->priv;
-       
-       if (priv->persist_stream == persist)
-               return;
-       
-       if (persist) {
-               priv->persist_stream = TRUE;
-               
-               if (priv->seekable && !priv->rawbuf) {
-                       priv->rawbuf = g_malloc (HEADER_RAW_INIT_SIZE);
-                       priv->rawleft = HEADER_RAW_INIT_SIZE - 1;
-                       priv->rawptr = priv->rawbuf;
-               }
-       } else {
-               priv->persist_stream = FALSE;
-               
-               if (priv->rawbuf) {
-                       g_free (priv->rawbuf);
-                       priv->rawbuf = NULL;
-                       priv->rawptr = NULL;
-                       priv->rawleft = 0;
-               }
-       }
+       parser->priv->persist_stream = persist;
 }
 
 
@@ -896,29 +867,20 @@ next_alloc_size (size_t n)
 } G_STMT_END
 
 #define raw_header_append(priv, start, len) G_STMT_START {                \
-       if (priv->rawbuf) {                                               \
-               if (priv->rawleft <= len) {                               \
-                       size_t hlen, hoff;                                \
-                                                                         \
-                       hoff = priv->rawptr - priv->rawbuf;               \
-                       hlen = next_alloc_size (hoff + len + 1);          \
-                                                                         \
-                       priv->rawbuf = g_realloc (priv->rawbuf, hlen);    \
-                       priv->rawptr = priv->rawbuf + hoff;               \
-                       priv->rawleft = (hlen - 1) - hoff;                \
-               }                                                         \
+       if (priv->rawleft <= len) {                                       \
+               size_t hlen, hoff;                                        \
                                                                          \
-               memcpy (priv->rawptr, start, len);                        \
-               priv->rawptr += len;                                      \
-               priv->rawleft -= len;                                     \
-       }                                                                 \
-} G_STMT_END
-
-#define raw_header_reset(priv) G_STMT_START {                             \
-       if (priv->rawbuf) {                                               \
-               priv->rawleft += priv->rawptr - priv->rawbuf;             \
-               priv->rawptr = priv->rawbuf;                              \
+               hoff = priv->rawptr - priv->rawbuf;                       \
+               hlen = next_alloc_size (hoff + len + 1);                  \
+                                                                         \
+               priv->rawbuf = g_realloc (priv->rawbuf, hlen);            \
+               priv->rawptr = priv->rawbuf + hoff;                       \
+               priv->rawleft = (hlen - 1) - hoff;                        \
        }                                                                 \
+                                                                         \
+       memcpy (priv->rawptr, start, len);                                \
+       priv->rawptr += len;                                              \
+       priv->rawleft -= len;                                             \
 } G_STMT_END
 
 static void
@@ -951,6 +913,12 @@ header_parse (GMimeParser *parser, HeaderRaw **tail)
        header->name = g_strndup (priv->headerbuf, (size_t) (inptr - priv->headerbuf));
        header->value = g_mime_strdup_trim (inptr + 1);
        
+       *priv->rawptr = '\0';
+       inptr = priv->rawbuf;
+       while (*inptr != ':')
+               inptr++;
+       
+       header->raw_value = g_strdup (inptr + 1);
        header->offset = priv->header_offset;
        
        (*tail)->next = header;
@@ -959,6 +927,9 @@ header_parse (GMimeParser *parser, HeaderRaw **tail)
        priv->headerleft += priv->headerptr - priv->headerbuf;
        priv->headerptr = priv->headerbuf;
        
+       priv->rawleft += priv->rawptr - priv->rawbuf;
+       priv->rawptr = priv->rawbuf;
+       
 #if defined (HAVE_GLIB_REGEX)
        if (priv->regex && g_regex_match (priv->regex, header->name, 0, NULL))
                priv->header_cb (parser, header->name, header->value,
@@ -1033,7 +1004,6 @@ parser_step_headers (GMimeParser *parser)
        size_t len;
        
        priv->midline = FALSE;
-       raw_header_reset (priv);
        header_raw_clear (&priv->headers);
        tail = (HeaderRaw *) &priv->headers;
        priv->headers_begin = parser_offset (priv, NULL);
@@ -1187,8 +1157,6 @@ parser_step_headers (GMimeParser *parser)
        
        priv->headers_end = parser_offset (priv, start);
        priv->state = GMIME_PARSER_STATE_HEADERS_END;
-       if (priv->rawbuf)
-               *priv->rawptr = '\0';
        priv->inptr = inptr;
        
        return 0;
@@ -1197,8 +1165,6 @@ parser_step_headers (GMimeParser *parser)
        
        priv->headers_end = parser_offset (priv, start);
        priv->state = GMIME_PARSER_STATE_COMPLETE;
-       if (priv->rawbuf)
-               *priv->rawptr = '\0';
        priv->inptr = start;
        
        return 0;
@@ -1207,8 +1173,6 @@ parser_step_headers (GMimeParser *parser)
        
        priv->headers_end = parser_offset (priv, start);
        priv->state = GMIME_PARSER_STATE_CONTENT;
-       if (priv->rawbuf)
-               *priv->rawptr = '\0';
        priv->inptr = start;
        
        return 0;
@@ -1671,7 +1635,7 @@ parser_scan_message_part (GMimeParser *parser, GMimeMessagePart *mpart, int *fou
        header = priv->headers;
        while (header) {
                if (g_ascii_strncasecmp (header->name, "Content-", 8) != 0)
-                       g_mime_object_append_header ((GMimeObject *) message, header->name, header->value);
+                       _g_mime_object_append_header ((GMimeObject *) message, header->name, header->value, 
header->raw_value, header->offset);
                header = header->next;
        }
        
@@ -1684,10 +1648,6 @@ parser_scan_message_part (GMimeParser *parser, GMimeMessagePart *mpart, int *fou
        content_type_destroy (content_type);
        message->mime_part = object;
        
-       /* set the same raw header stream on the message's header-list */
-       if ((stream = g_mime_header_list_get_stream (object->headers)))
-               g_mime_header_list_set_stream (((GMimeObject *) message)->headers, stream);
-       
        g_mime_message_part_set_message (mpart, message);
        g_object_unref (message);
 }
@@ -1697,7 +1657,6 @@ parser_construct_leaf_part (GMimeParser *parser, ContentType *content_type, gboo
 {
        struct _GMimeParserPrivate *priv = parser->priv;
        GMimeObject *object;
-       GMimeStream *stream;
        HeaderRaw *header;
        
        g_assert (priv->state >= GMIME_PARSER_STATE_HEADERS_END);
@@ -1715,23 +1674,12 @@ parser_construct_leaf_part (GMimeParser *parser, ContentType *content_type, gboo
        header = priv->headers;
        while (header) {
                if (!toplevel || !g_ascii_strncasecmp (header->name, "Content-", 8))
-                       g_mime_object_append_header (object, header->name, header->value);
+                       _g_mime_object_append_header (object, header->name, header->value, header->raw_value, 
header->offset);
                header = header->next;
        }
        
        header_raw_clear (&priv->headers);
        
-       /* set the raw header stream on the header-list */
-       if (priv->persist_stream && priv->seekable)
-               stream = g_mime_stream_substream (priv->stream, priv->headers_begin, priv->headers_end);
-       else
-               stream = g_mime_stream_mem_new_with_buffer (priv->rawbuf, priv->rawptr - priv->rawbuf);
-       
-       g_mime_header_list_set_stream (object->headers, stream);
-       g_object_unref (stream);
-       
-       raw_header_reset (priv);
-       
        if (priv->state == GMIME_PARSER_STATE_HEADERS_END) {
                /* skip empty line after headers */
                if (parser_step (parser) == GMIME_PARSER_STATE_ERROR) {
@@ -1863,23 +1811,12 @@ parser_construct_multipart (GMimeParser *parser, ContentType *content_type, gboo
        header = priv->headers;
        while (header) {
                if (!toplevel || !g_ascii_strncasecmp (header->name, "Content-", 8))
-                       g_mime_object_append_header (object, header->name, header->value);
+                       _g_mime_object_append_header (object, header->name, header->value, header->raw_value, 
header->offset);
                header = header->next;
        }
        
        header_raw_clear (&priv->headers);
        
-       /* set the raw header stream on the header-list */
-       if (priv->persist_stream && priv->seekable)
-               stream = g_mime_stream_substream (priv->stream, priv->headers_begin, priv->headers_end);
-       else
-               stream = g_mime_stream_mem_new_with_buffer (priv->rawbuf, priv->rawptr - priv->rawbuf);
-       
-       g_mime_header_list_set_stream (object->headers, stream);
-       g_object_unref (stream);
-       
-       raw_header_reset (priv);
-       
        multipart = (GMimeMultipart *) object;
        
        if (priv->state == GMIME_PARSER_STATE_HEADERS_END) {
@@ -1996,7 +1933,7 @@ parser_construct_message (GMimeParser *parser)
                }
                
                if (g_ascii_strncasecmp (header->name, "Content-", 8) != 0)
-                       g_mime_object_append_header ((GMimeObject *) message, header->name, header->value);
+                       _g_mime_object_append_header ((GMimeObject *) message, header->name, header->value, 
header->raw_value, header->offset);
                header = header->next;
        }
        
@@ -2015,10 +1952,6 @@ parser_construct_message (GMimeParser *parser)
        content_type_destroy (content_type);
        message->mime_part = object;
        
-       /* set the same raw header stream on the message's header-list */
-       if ((stream = g_mime_header_list_get_stream (object->headers)))
-               g_mime_header_list_set_stream (((GMimeObject *) message)->headers, stream);
-       
        if (priv->scan_from) {
                priv->state = GMIME_PARSER_STATE_FROM;
                parser_pop_boundary (parser);
diff --git a/gmime/gmime-part.c b/gmime/gmime-part.c
index b37c53d..8b30526 100644
--- a/gmime/gmime-part.c
+++ b/gmime/gmime-part.c
@@ -52,17 +52,21 @@
  * sub-parts).
  **/
 
+extern void _g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char *value, 
const char *raw_value, gint64 offset);
+extern void _g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char *value, const 
char *raw_value, gint64 offset);
+extern void _g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value, const 
char *raw_value, gint64 offset);
+
 /* GObject class methods */
 static void g_mime_part_class_init (GMimePartClass *klass);
 static void g_mime_part_init (GMimePart *mime_part, GMimePartClass *klass);
 static void g_mime_part_finalize (GObject *object);
 
 /* GMimeObject class methods */
-static void mime_part_prepend_header (GMimeObject *object, const char *header, const char *value);
-static void mime_part_append_header (GMimeObject *object, const char *header, const char *value);
-static void mime_part_set_header (GMimeObject *object, const char *header, const char *value);
+static void mime_part_prepend_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset);
+static void mime_part_append_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset);
+static void mime_part_set_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset);
 static gboolean mime_part_remove_header (GMimeObject *object, const char *header);
-static ssize_t mime_part_write_to_stream (GMimeObject *object, GMimeStream *stream);
+static ssize_t mime_part_write_to_stream (GMimeObject *object, GMimeStream *stream, gboolean content_only);
 static void mime_part_encode (GMimeObject *object, GMimeEncodingConstraint constraint);
 
 /* GMimePart class methods */
@@ -216,30 +220,30 @@ process_header (GMimeObject *object, const char *header, const char *value)
 }
 
 static void
-mime_part_prepend_header (GMimeObject *object, const char *header, const char *value)
+mime_part_prepend_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, 
gint64 offset)
 {
        if (!process_header (object, header, value))
-               GMIME_OBJECT_CLASS (parent_class)->prepend_header (object, header, value);
+               GMIME_OBJECT_CLASS (parent_class)->prepend_header (object, header, value, raw_value, offset);
        else
-               g_mime_header_list_prepend (object->headers, header, value);
+               _g_mime_header_list_prepend (object->headers, header, value, raw_value, offset);
 }
 
 static void
-mime_part_append_header (GMimeObject *object, const char *header, const char *value)
+mime_part_append_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, 
gint64 offset)
 {
        if (!process_header (object, header, value))
-               GMIME_OBJECT_CLASS (parent_class)->append_header (object, header, value);
+               GMIME_OBJECT_CLASS (parent_class)->append_header (object, header, value, raw_value, offset);
        else
-               g_mime_header_list_append (object->headers, header, value);
+               _g_mime_header_list_append (object->headers, header, value, raw_value, offset);
 }
 
 static void
-mime_part_set_header (GMimeObject *object, const char *header, const char *value)
+mime_part_set_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, 
gint64 offset)
 {
        if (!process_header (object, header, value))
-               GMIME_OBJECT_CLASS (parent_class)->set_header (object, header, value);
+               GMIME_OBJECT_CLASS (parent_class)->set_header (object, header, value, raw_value, offset);
        else
-               g_mime_header_list_set (object->headers, header, value);
+               _g_mime_header_list_set (object->headers, header, value, raw_value, offset);
 }
 
 static gboolean
@@ -356,22 +360,24 @@ write_content (GMimePart *part, GMimeStream *stream)
 }
 
 static ssize_t
-mime_part_write_to_stream (GMimeObject *object, GMimeStream *stream)
+mime_part_write_to_stream (GMimeObject *object, GMimeStream *stream, gboolean content_only)
 {
        GMimePart *mime_part = (GMimePart *) object;
        ssize_t nwritten, total = 0;
        
-       /* write the content headers */
-       if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1)
-               return -1;
-       
-       total += nwritten;
-       
-       /* terminate the headers */
-       if (g_mime_stream_write (stream, "\n", 1) == -1)
-               return -1;
-       
-       total++;
+       if (!content_only) {
+               /* write the content headers */
+               if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1)
+                       return -1;
+               
+               total += nwritten;
+               
+               /* terminate the headers */
+               if (g_mime_stream_write (stream, "\n", 1) == -1)
+                       return -1;
+               
+               total++;
+       }
        
        if ((nwritten = write_content (mime_part, stream)) == -1)
                return -1;
diff --git a/tests/test-parser.c b/tests/test-parser.c
index 56bd763..9fd0416 100644
--- a/tests/test-parser.c
+++ b/tests/test-parser.c
@@ -193,11 +193,8 @@ test_parser (GMimeStream *stream)
        {
                GMimeStream *stream;
                
-               g_mime_header_list_set_stream (GMIME_OBJECT (message)->headers, NULL);
-               
                fprintf (stdout, "\nTesting preservation of headers...\n\n");
                stream = g_mime_stream_file_new (stdout);
-               /*g_mime_header_set_stream (GMIME_OBJECT (message)->headers, NULL);*/
                g_mime_header_list_write_to_stream (GMIME_OBJECT (message)->headers, stream);
                g_mime_stream_flush (stream);
                GMIME_STREAM_FILE (stream)->fp = NULL;


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