[gmime] Rearchitected the way GMimeObject's process added/removed headers



commit e82bf3117c7cc6ea2b66b4e3adf772bd1132b005
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Sun Mar 12 12:32:10 2017 -0400

    Rearchitected the way GMimeObject's process added/removed headers
    
    This now works based on an event system similar to MimeKit's
    
    Headers get added/removed/set on the GMimeHeaderList directly
    which then emits a 'changed' event that GMimeObject listens
    to and dispatches appropriately to header_added(), header_changed(),
    header_removed(), or headers_cleared().
    
    These virtual methods are where the work now gets done to update
    the object's parsed representation of various headers.

 PORTING                         |   11 +-
 docs/reference/changes-3.0.sgml |    2 +-
 gmime/gmime-internal.h          |    2 +
 gmime/gmime-message-partial.c   |   35 ----
 gmime/gmime-message.c           |  253 ++++++++++++------------------
 gmime/gmime-object.c            |  330 ++++++++++++++++++++++-----------------
 gmime/gmime-object.h            |    9 +-
 gmime/gmime-part.c              |  113 +++++++++-----
 tests/test-headers.c            |    2 +-
 tests/test-parser.c             |    2 +-
 10 files changed, 375 insertions(+), 384 deletions(-)
---
diff --git a/PORTING b/PORTING
index 4669de7..f25c199 100644
--- a/PORTING
+++ b/PORTING
@@ -43,12 +43,11 @@ Porting from GMime 2.6 to GMime 3.0
   decoder API's take a GMimeParserOptions argument that allows for
   specifying fallback charsets.
 
-- GMimeObject's prepend_header(), append_header(), and set_header() virtual
-  methods now all take a const char *raw_value and gint64 offset arguments.
-  The raw_value is the raw header value cloned exactly as the parser found
-  it in the stream (meaning it retains the original folding). The 'value'
-  argument remains as it has always been, an unfolded (but still encoded)
-  header value.
+- GMimeObject's prepend_header(), append_header(), set_header(), get_header(),
+  and remove_header() virtual methods have all been removed. They have been
+  replaced by the header_added(), header_changed(), header_removed(), and
+  headers_cleared() virtual methods to allow users to set headers on the
+  GMimeHeaderList directly and still get notifications of those changes.
 
 - g_mime_object_new() and g_mime_object_new_with_type() both now take a
   GMimeParserOptions argument.
diff --git a/docs/reference/changes-3.0.sgml b/docs/reference/changes-3.0.sgml
index d990eee..76ade30 100644
--- a/docs/reference/changes-3.0.sgml
+++ b/docs/reference/changes-3.0.sgml
@@ -37,7 +37,7 @@
     </itemizedlist>
     <para>Other API changes:</para>
       <listitem><para><function>g_mime_set_user_charsets()</function> and 
<function>g_mime_user_charsets()</function> have been removed. All encoding API's now have a way to specify a 
charset to use and all decoder API's take a GMimeParserOptions argument that allows for specifying fallback 
charsets.</para></listitem>
-      <listitem><para>GMimeObject's prepend_header(), append_header(), and set_header() virtual methods now 
all take a const char *raw_value and gint64 offset arguments. The raw_value is the raw header value cloned 
exactly as the parser found it in the stream (meaning it retains the original folding). The 'value' argument 
remains as it has always been, an unfolded (but still encoded) header value.</para></listitem>
+      <listitem><para>GMimeObject's prepend_header(), append_header(), set_header(), get_header(), and 
remove_header() virtual methods have all been removed. They have been replaced by the header_added(), 
header_changed(), header_removed(), and headers_cleared() virtual methods to allow users to set headers on 
the GMimeHeaderList directly and still get notifications of those changes.</para></listitem>
       <listitem><para><function>g_mime_object_new()</function> and 
<function>g_mime_object_new_with_type()</function> both now take a GMimeParserOptions 
argument.</para></listitem>
       <listitem><para><function>g_mime_param_new_from_string()</function> has been replaced by 
<function>g_mime_param_parse()</function> and now takes a GMimeParserOptions argument.</para></listitem>
       <listitem><para><function>g_mime_content_type_new_from_string()</function> has been replaced by 
<function>g_mime_content_type_parse()</function> and now takes a GMimeParserOptions 
argument.</para></listitem>
diff --git a/gmime/gmime-internal.h b/gmime/gmime-internal.h
index 957291e..5d184a4 100644
--- a/gmime/gmime-internal.h
+++ b/gmime/gmime-internal.h
@@ -60,6 +60,8 @@ G_GNUC_INTERNAL void _g_mime_header_list_set (GMimeHeaderList *headers, const ch
 G_GNUC_INTERNAL GMimeEvent *_g_mime_header_list_get_changed_event (GMimeHeaderList *headers);
 
 /* GMimeObject */
+G_GNUC_INTERNAL void _g_mime_object_block_header_list_changed (GMimeObject *object);
+G_GNUC_INTERNAL void _g_mime_object_unblock_header_list_changed (GMimeObject *object);
 G_GNUC_INTERNAL void _g_mime_object_set_content_type (GMimeObject *object, GMimeContentType *content_type);
 G_GNUC_INTERNAL void _g_mime_object_prepend_header (GMimeObject *object, const char *header, const char 
*value, const char *raw_value, gint64 offset);
 G_GNUC_INTERNAL void _g_mime_object_append_header (GMimeObject *object, const char *header, const char 
*value, const char *raw_value, gint64 offset);
diff --git a/gmime/gmime-message-partial.c b/gmime/gmime-message-partial.c
index d2125f1..cadd313 100644
--- a/gmime/gmime-message-partial.c
+++ b/gmime/gmime-message-partial.c
@@ -48,9 +48,6 @@ 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, 
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 void message_partial_set_content_type (GMimeObject *object, GMimeContentType *content_type);
 
 
@@ -92,9 +89,6 @@ g_mime_message_partial_class_init (GMimeMessagePartialClass *klass)
        
        gobject_class->finalize = g_mime_message_partial_finalize;
        
-       object_class->prepend_header = message_partial_prepend_header;
-       object_class->append_header = message_partial_append_header;
-       object_class->set_header = message_partial_set_header;
        object_class->set_content_type = message_partial_set_content_type;
 }
 
@@ -116,35 +110,6 @@ g_mime_message_partial_finalize (GObject *object)
        G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-static void
-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, raw_value, offset);
-}
-
-static void
-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, raw_value, offset);
-}
-
-static void
-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, raw_value, offset);
-}
 
 static void
 message_partial_set_content_type (GMimeObject *object, GMimeContentType *content_type)
diff --git a/gmime/gmime-message.c b/gmime/gmime-message.c
index 70eac15..9466eea 100644
--- a/gmime/gmime-message.c
+++ b/gmime/gmime-message.c
@@ -55,11 +55,11 @@ 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, 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 void message_header_added    (GMimeObject *object, GMimeHeader *header);
+static void message_header_changed  (GMimeObject *object, GMimeHeader *header);
+static void message_header_removed  (GMimeObject *object, GMimeHeader *header);
+static void message_headers_cleared (GMimeObject *object);
+
 static char *message_get_headers (GMimeObject *object);
 static ssize_t message_write_to_stream (GMimeObject *object, GMimeStream *stream, gboolean content_only);
 static void message_encode (GMimeObject *object, GMimeEncodingConstraint constraint);
@@ -144,11 +144,10 @@ g_mime_message_class_init (GMimeMessageClass *klass)
        
        gobject_class->finalize = g_mime_message_finalize;
        
-       object_class->prepend_header = message_prepend_header;
-       object_class->append_header = message_append_header;
-       object_class->remove_header = message_remove_header;
-       object_class->set_header = message_set_header;
-       object_class->get_header = message_get_header;
+       object_class->header_added = message_header_added;
+       object_class->header_changed = message_header_changed;
+       object_class->header_removed = message_header_removed;
+       object_class->headers_cleared = message_headers_cleared;
        object_class->get_headers = message_get_headers;
        object_class->write_to_stream = message_write_to_stream;
        object_class->encode = message_encode;
@@ -658,84 +657,86 @@ static const char *message_headers[] = {
        "MIME-Version",
 };
 
-enum {
-       PREPEND,
-       APPEND,
-       SET
-};
-
 static void
-message_add_addresses_from_string (GMimeParserOptions *options, GMimeMessage *message, int action, 
GMimeAddressType type, const char *str)
+message_update_addresses (GMimeMessage *message, GMimeParserOptions *options, GMimeAddressType type)
 {
+       GMimeHeaderList *headers = ((GMimeObject *) message)->headers;
        InternetAddressList *addrlist, *list;
+       const char *name, *value;
+       GMimeHeader *header;
+       int count, i;
+       
+       block_changed_event (message, type);
        
        addrlist = message->addrlists[type];
        
-       if (action == SET)
-               internet_address_list_clear (addrlist);
+       internet_address_list_clear (addrlist);
        
-       if ((list = internet_address_list_parse (options, str))) {
-               if (action == PREPEND)
-                       internet_address_list_prepend (addrlist, list);
-               else
-                       internet_address_list_append (addrlist, list);
+       count = g_mime_header_list_get_count (headers);
+       for (i = 0; i < count; i++) {
+               header = g_mime_header_list_get_header (headers, i);
+               name = g_mime_header_get_name (header);
                
-               g_object_unref (list);
+               if (g_ascii_strcasecmp (address_types[type].name, name) != 0)
+                       continue;
+               
+               if ((value = g_mime_header_get_value (header))) {
+                       if ((list = internet_address_list_parse (options, value))) {
+                               internet_address_list_append (addrlist, list);
+                               g_object_unref (list);
+                       }
+               }
        }
+       
+       unblock_changed_event (message, type);
 }
 
-static gboolean
-process_header (GMimeObject *object, int action, const char *header, const char *value)
+static void
+process_header (GMimeObject *object, GMimeHeader *header)
 {
        GMimeParserOptions *options = _g_mime_header_list_get_options (object->headers);
        GMimeMessage *message = (GMimeMessage *) object;
-       InternetAddressList *addrlist;
+       const char *name, *value;
        time_t date;
        int offset;
        guint i;
        
+       name = g_mime_header_get_name (header);
+       
        for (i = 0; i < G_N_ELEMENTS (message_headers); i++) {
-               if (!g_ascii_strcasecmp (message_headers[i], header))
+               if (!g_ascii_strcasecmp (message_headers[i], name))
                        break;
        }
        
        switch (i) {
        case HEADER_SENDER:
-               block_changed_event (message, GMIME_ADDRESS_TYPE_SENDER);
-               message_add_addresses_from_string (options, message, SET, GMIME_ADDRESS_TYPE_SENDER, value);
-               unblock_changed_event (message, GMIME_ADDRESS_TYPE_SENDER);
+               message_update_addresses (message, options, GMIME_ADDRESS_TYPE_SENDER);
                break;
        case HEADER_FROM:
-               block_changed_event (message, GMIME_ADDRESS_TYPE_FROM);
-               message_add_addresses_from_string (options, message, SET, GMIME_ADDRESS_TYPE_FROM, value);
-               unblock_changed_event (message, GMIME_ADDRESS_TYPE_FROM);
+               message_update_addresses (message, options, GMIME_ADDRESS_TYPE_FROM);
                break;
        case HEADER_REPLY_TO:
-               block_changed_event (message, GMIME_ADDRESS_TYPE_REPLY_TO);
-               message_add_addresses_from_string (options, message, SET, GMIME_ADDRESS_TYPE_REPLY_TO, value);
-               unblock_changed_event (message, GMIME_ADDRESS_TYPE_REPLY_TO);
+               message_update_addresses (message, options, GMIME_ADDRESS_TYPE_REPLY_TO);
                break;
        case HEADER_TO:
-               block_changed_event (message, GMIME_ADDRESS_TYPE_TO);
-               message_add_addresses_from_string (options, message, action, GMIME_ADDRESS_TYPE_TO, value);
-               unblock_changed_event (message, GMIME_ADDRESS_TYPE_TO);
+               message_update_addresses (message, options, GMIME_ADDRESS_TYPE_TO);
                break;
        case HEADER_CC:
-               block_changed_event (message, GMIME_ADDRESS_TYPE_CC);
-               message_add_addresses_from_string (options, message, action, GMIME_ADDRESS_TYPE_CC, value);
-               unblock_changed_event (message, GMIME_ADDRESS_TYPE_CC);
+               message_update_addresses (message, options, GMIME_ADDRESS_TYPE_CC);
                break;
        case HEADER_BCC:
-               block_changed_event (message, GMIME_ADDRESS_TYPE_BCC);
-               message_add_addresses_from_string (options, message, action, GMIME_ADDRESS_TYPE_BCC, value);
-               unblock_changed_event (message, GMIME_ADDRESS_TYPE_BCC);
+               message_update_addresses (message, options, GMIME_ADDRESS_TYPE_BCC);
                break;
        case HEADER_SUBJECT:
                g_free (message->subject);
-               message->subject = g_mime_utils_header_decode_text (options, value);
+               
+               if ((value = g_mime_header_get_value (header)))
+                       message->subject = g_mime_utils_header_decode_text (options, value);
+               else
+                       message->subject = NULL;
                break;
        case HEADER_DATE:
-               if (value) {
+               if ((value = g_mime_header_get_value (header))) {
                        date = g_mime_utils_header_decode_date (value, &offset);
                        message->date = date;
                        message->tz_offset = offset;
@@ -743,139 +744,66 @@ process_header (GMimeObject *object, int action, const char *header, const char
                break;
        case HEADER_MESSAGE_ID:
                g_free (message->message_id);
-               message->message_id = g_mime_utils_decode_message_id (value);
-               break;
-       case HEADER_MIME_VERSION:
+               
+               if ((value = g_mime_header_get_value (header)))
+                       message->message_id = g_mime_utils_decode_message_id (value);
+               else
+                       message->message_id = NULL;
                break;
-       default:
-               return FALSE;
-       }
-       
-       return TRUE;
-}
-
-static void
-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, raw_value, offset);
-               return;
        }
-       
-       if (!process_header (object, PREPEND, 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, raw_value, offset);
 }
 
 static void
-message_append_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, 
gint64 offset)
+message_header_added (GMimeObject *object, GMimeHeader *header)
 {
-       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, raw_value, offset);
-               return;
-       }
+       process_header (object, header);
        
-       if (!process_header (object, APPEND, 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, raw_value, offset);
+       GMIME_OBJECT_CLASS (parent_class)->header_added (object, header);
 }
 
 static void
-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, raw_value, offset);
-               return;
-       }
-       
-       if (!process_header (object, SET, 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, raw_value, offset);
-}
-
-static const char *
-message_get_header (GMimeObject *object, const char *header)
+message_header_changed (GMimeObject *object, GMimeHeader *header)
 {
-       GMimeMessage *message = (GMimeMessage *) object;
-       const char *value;
-       
-       /* Content-* headers don't belong on the message, they belong on the part. */
-       if (g_ascii_strncasecmp ("Content-", header, 8) != 0) {
-               if ((value = GMIME_OBJECT_CLASS (parent_class)->get_header (object, header)))
-                       return value;
-               
-               if (!g_ascii_strcasecmp ("MIME-Version", header))
-                       return "1.0";
-       } else if (message->mime_part) {
-               return g_mime_object_get_header (message->mime_part, header);
-       }
+       process_header (object, header);
        
-       return NULL;
+       GMIME_OBJECT_CLASS (parent_class)->header_changed (object, header);
 }
 
 static void
-remove_address_header (GMimeMessage *message, GMimeAddressType type)
-{
-       InternetAddressList *addrlist;
-       
-       block_changed_event (message, type);
-       addrlist = message->addrlists[type];
-       internet_address_list_clear (addrlist);
-       unblock_changed_event (message, type);
-}
-
-static gboolean
-message_remove_header (GMimeObject *object, const char *header)
+message_header_removed (GMimeObject *object, GMimeHeader *header)
 {
+       GMimeParserOptions *options = _g_mime_header_list_get_options (object->headers);
        GMimeMessage *message = (GMimeMessage *) object;
+       const char *name;
+       time_t date;
+       int offset;
        guint i;
        
-       /* Content-* headers don't belong on the message, they belong on the part. */
-       if (!g_ascii_strncasecmp ("Content-", header, 8)) {
-               if (message->mime_part)
-                       return g_mime_object_remove_header (message->mime_part, header);
-               
-               return FALSE;
-       }
+       name = g_mime_header_get_name (header);
        
        for (i = 0; i < G_N_ELEMENTS (message_headers); i++) {
-               if (!g_ascii_strcasecmp (message_headers[i], header))
+               if (!g_ascii_strcasecmp (message_headers[i], name))
                        break;
        }
        
        switch (i) {
        case HEADER_SENDER:
-               remove_address_header (message, GMIME_ADDRESS_TYPE_SENDER);
+               message_update_addresses (message, options, GMIME_ADDRESS_TYPE_SENDER);
                break;
        case HEADER_FROM:
-               remove_address_header (message, GMIME_ADDRESS_TYPE_FROM);
+               message_update_addresses (message, options, GMIME_ADDRESS_TYPE_FROM);
                break;
        case HEADER_REPLY_TO:
-               remove_address_header (message, GMIME_ADDRESS_TYPE_REPLY_TO);
+               message_update_addresses (message, options, GMIME_ADDRESS_TYPE_REPLY_TO);
                break;
        case HEADER_TO:
-               remove_address_header (message, GMIME_ADDRESS_TYPE_TO);
+               message_update_addresses (message, options, GMIME_ADDRESS_TYPE_TO);
                break;
        case HEADER_CC:
-               remove_address_header (message, GMIME_ADDRESS_TYPE_CC);
+               message_update_addresses (message, options, GMIME_ADDRESS_TYPE_CC);
                break;
        case HEADER_BCC:
-               remove_address_header (message, GMIME_ADDRESS_TYPE_BCC);
+               message_update_addresses (message, options, GMIME_ADDRESS_TYPE_BCC);
                break;
        case HEADER_SUBJECT:
                g_free (message->subject);
@@ -889,11 +817,31 @@ message_remove_header (GMimeObject *object, const char *header)
                g_free (message->message_id);
                message->message_id = NULL;
                break;
-       default:
-               break;
        }
        
-       return GMIME_OBJECT_CLASS (parent_class)->remove_header (object, header);
+       GMIME_OBJECT_CLASS (parent_class)->header_removed (object, header);
+}
+
+static void
+message_headers_cleared (GMimeObject *object)
+{
+       GMimeMessage *message = (GMimeMessage *) object;
+       guint i;
+       
+       for (i = 0; i < N_ADDRESS_TYPES; i++) {
+               block_changed_event (message, i);
+               internet_address_list_clear (message->addrlists[i]);
+               unblock_changed_event (message, i);
+       }
+       
+       g_free (message->message_id);
+       message->message_id = NULL;
+       g_free (message->subject);
+       message->subject = NULL;
+       message->tz_offset = 0;
+       message->date = 0;
+       
+       GMIME_OBJECT_CLASS (parent_class)->headers_cleared (object);
 }
 
 
@@ -1044,8 +992,11 @@ g_mime_message_new (gboolean pretty_headers)
        if (pretty_headers) {
                /* Populate with the "standard" rfc822 headers so we can have a standard order */
                headers = ((GMimeObject *) message)->headers;
+               
+               _g_mime_object_block_header_list_changed ((GMimeObject *) message);
                for (i = 0; i < G_N_ELEMENTS (rfc822_headers); i++) 
                        g_mime_header_list_set (headers, rfc822_headers[i], NULL);
+               _g_mime_object_unblock_header_list_changed ((GMimeObject *) message);
        }
        
        return message;
@@ -1161,7 +1112,11 @@ sync_internet_address_list (InternetAddressList *list, GMimeMessage *message, co
        char *string;
        
        string = internet_address_list_to_string (list, TRUE);
+       
+       _g_mime_object_block_header_list_changed (object);
        g_mime_header_list_set (object->headers, name, string);
+       _g_mime_object_unblock_header_list_changed (object);
+       
        g_free (string);
 }
 
diff --git a/gmime/gmime-object.c b/gmime/gmime-object.c
index 7965d3e..5a1a2b4 100644
--- a/gmime/gmime-object.c
+++ b/gmime/gmime-object.c
@@ -62,11 +62,11 @@ 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, 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_header_added    (GMimeObject *object, GMimeHeader *header);
+static void object_header_changed  (GMimeObject *object, GMimeHeader *header);
+static void object_header_removed  (GMimeObject *object, GMimeHeader *header);
+static void object_headers_cleared (GMimeObject *object);
+
 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, gboolean content_only);
@@ -75,6 +75,7 @@ static void object_encode (GMimeObject *object, GMimeEncodingConstraint constrai
 static ssize_t write_content_type (GMimeParserOptions *options, GMimeStream *stream, const char *name, const 
char *value);
 static ssize_t write_disposition (GMimeParserOptions *options, GMimeStream *stream, const char *name, const 
char *value);
 
+static void header_list_changed (GMimeHeaderList *headers, GMimeHeaderListChangedEventArgs *args, 
GMimeObject *object);
 static void content_type_changed (GMimeContentType *content_type, gpointer args, GMimeObject *object);
 static void content_disposition_changed (GMimeContentDisposition *disposition, gpointer args, GMimeObject 
*object);
 
@@ -116,14 +117,13 @@ g_mime_object_class_init (GMimeObjectClass *klass)
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
        
        parent_class = g_type_class_ref (G_TYPE_OBJECT);
-
+       
        object_class->finalize = g_mime_object_finalize;
        
-       klass->prepend_header = object_prepend_header;
-       klass->append_header = object_append_header;
-       klass->remove_header = object_remove_header;
-       klass->set_header = object_set_header;
-       klass->get_header = object_get_header;
+       klass->header_added = object_header_added;
+       klass->header_changed = object_header_changed;
+       klass->header_removed = object_header_removed;
+       klass->headers_cleared = object_headers_cleared;
        klass->set_content_type = object_set_content_type;
        klass->get_headers = object_get_headers;
        klass->write_to_stream = object_write_to_stream;
@@ -133,7 +133,12 @@ g_mime_object_class_init (GMimeObjectClass *klass)
 static void
 g_mime_object_init (GMimeObject *object, GMimeObjectClass *klass)
 {
+       GMimeEvent *changed;
+       
        object->headers = g_mime_header_list_new (g_mime_parser_options_get_default ());
+       changed = _g_mime_header_list_get_changed_event (object->headers);
+       g_mime_event_add (changed, (GMimeEventCallback) header_list_changed, object);
+       
        object->content_type = NULL;
        object->disposition = NULL;
        object->content_id = NULL;
@@ -147,25 +152,158 @@ static void
 g_mime_object_finalize (GObject *object)
 {
        GMimeObject *mime = (GMimeObject *) object;
+       GMimeEvent *event;
        
        if (mime->content_type) {
-               g_mime_event_remove (mime->content_type->priv, (GMimeEventCallback) content_type_changed, 
object);
+               event = mime->content_type->priv;
+               g_mime_event_remove (event, (GMimeEventCallback) content_type_changed, object);
                g_object_unref (mime->content_type);
        }
        
        if (mime->disposition) {
-               g_mime_event_remove (mime->disposition->priv, (GMimeEventCallback) 
content_disposition_changed, object);
+               event = mime->disposition->priv;
+               g_mime_event_remove (event, (GMimeEventCallback) content_disposition_changed, object);
                g_object_unref (mime->disposition);
        }
        
-       if (mime->headers)
+       if (mime->headers) {
+               event = _g_mime_header_list_get_changed_event (mime->headers);
+               g_mime_event_remove (event, (GMimeEventCallback) header_list_changed, object);
                g_mime_header_list_destroy (mime->headers);
+       }
        
        g_free (mime->content_id);
        
        G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+enum {
+       HEADER_CONTENT_DISPOSITION,
+       HEADER_CONTENT_TYPE,
+       HEADER_CONTENT_ID,
+       HEADER_UNKNOWN,
+};
+
+static char *content_headers[] = {
+       "Content-Disposition",
+       "Content-Type",
+       "Content-Id",
+};
+
+static void
+object_header_added (GMimeObject *object, GMimeHeader *header)
+{
+       object_header_changed (object, header);
+}
+
+static void
+object_header_changed (GMimeObject *object, GMimeHeader *header)
+{
+       GMimeParserOptions *options = _g_mime_header_list_get_options (object->headers);
+       GMimeContentDisposition *disposition;
+       GMimeContentType *content_type;
+       const char *name, *value;
+       guint i;
+       
+       value = g_mime_header_get_value (header);
+       name = g_mime_header_get_name (header);
+       
+       if (g_ascii_strncasecmp (name, "Content-", 8) != 0)
+               return;
+       
+       for (i = 0; i < G_N_ELEMENTS (content_headers); i++) {
+               if (!g_ascii_strcasecmp (content_headers[i] + 8, name + 8))
+                       break;
+       }
+       
+       switch (i) {
+       case HEADER_CONTENT_DISPOSITION:
+               disposition = g_mime_content_disposition_parse (options, value);
+               _g_mime_object_set_content_disposition (object, disposition);
+               g_object_unref (disposition);
+               break;
+       case HEADER_CONTENT_TYPE:
+               content_type = g_mime_content_type_parse (options, value);
+               _g_mime_object_set_content_type (object, content_type);
+               g_object_unref (content_type);
+               break;
+       case HEADER_CONTENT_ID:
+               g_free (object->content_id);
+               object->content_id = g_mime_utils_decode_message_id (value);
+               break;
+       }
+}
+
+static void
+object_header_removed (GMimeObject *object, GMimeHeader *header)
+{
+       GMimeEvent *event;
+       const char *name;
+       guint i;
+       
+       name = g_mime_header_get_name (header);
+       
+       if (g_ascii_strncasecmp (name, "Content-", 8) != 0)
+               return;
+       
+       for (i = 0; i < G_N_ELEMENTS (content_headers); i++) {
+               if (!g_ascii_strcasecmp (content_headers[i] + 8, name + 8))
+                       break;
+       }
+       
+       switch (i) {
+       case HEADER_CONTENT_DISPOSITION:
+               if (object->disposition) {
+                       event = object->disposition->priv;
+                       g_mime_event_remove (event, (GMimeEventCallback) content_disposition_changed, object);
+                       g_object_unref (object->disposition);
+                       object->disposition = NULL;
+               }
+               break;
+       case HEADER_CONTENT_TYPE:
+               /* never allow the removal of the Content-Type header */
+               break;
+       case HEADER_CONTENT_ID:
+               g_free (object->content_id);
+               object->content_id = NULL;
+               break;
+       }
+}
+
+static void
+object_headers_cleared (GMimeObject *object)
+{
+       GMimeEvent *event;
+       
+       if (object->disposition) {
+               event = object->disposition->priv;
+               g_mime_event_remove (event, (GMimeEventCallback) content_disposition_changed, object);
+               g_object_unref (object->disposition);
+               object->disposition = NULL;
+       }
+       
+       g_free (object->content_id);
+       object->content_id = NULL;
+}
+
+static void
+header_list_changed (GMimeHeaderList *headers, GMimeHeaderListChangedEventArgs *args, GMimeObject *object)
+{
+       switch (args->action) {
+       case GMIME_HEADER_LIST_CHANGED_ACTION_ADDED:
+               GMIME_OBJECT_GET_CLASS (object)->header_added (object, args->header);
+               break;
+       case GMIME_HEADER_LIST_CHANGED_ACTION_CHANGED:
+               GMIME_OBJECT_GET_CLASS (object)->header_changed (object, args->header);
+               break;
+       case GMIME_HEADER_LIST_CHANGED_ACTION_REMOVED:
+               GMIME_OBJECT_GET_CLASS (object)->header_removed (object, args->header);
+               break;
+       case GMIME_HEADER_LIST_CHANGED_ACTION_CLEARED:
+               GMIME_OBJECT_GET_CLASS (object)->headers_cleared (object);
+               break;
+       }
+}
 
 static ssize_t
 write_content_type (GMimeParserOptions *options, GMimeStream *stream, const char *name, const char *value)
@@ -193,6 +331,24 @@ write_content_type (GMimeParserOptions *options, GMimeStream *stream, const char
        return nwritten;
 }
 
+void
+_g_mime_object_block_header_list_changed (GMimeObject *object)
+{
+       GMimeEvent *event;
+       
+       event = _g_mime_header_list_get_changed_event (object->headers);
+       g_mime_event_block (event, (GMimeEventCallback) header_list_changed, object);
+}
+
+void
+_g_mime_object_unblock_header_list_changed (GMimeObject *object)
+{
+       GMimeEvent *event;
+       
+       event = _g_mime_header_list_get_changed_event (object->headers);
+       g_mime_event_unblock (event, (GMimeEventCallback) header_list_changed, object);
+}
+
 static void
 content_type_changed (GMimeContentType *content_type, gpointer args, GMimeObject *object)
 {
@@ -213,7 +369,9 @@ content_type_changed (GMimeContentType *content_type, gpointer args, GMimeObject
        g_string_free (string, FALSE);
        
        type = p + strlen ("Content-Type: ");
+       _g_mime_object_block_header_list_changed (object);
        g_mime_header_list_set (object->headers, "Content-Type", type);
+       _g_mime_object_unblock_header_list_changed (object);
        g_free (p);
 }
 
@@ -244,6 +402,8 @@ content_disposition_changed (GMimeContentDisposition *disposition, gpointer args
 {
        char *str;
        
+       _g_mime_object_block_header_list_changed (object);
+       
        if (object->disposition) {
                str = g_mime_content_disposition_to_string (object->disposition, FALSE);
                g_mime_header_list_set (object->headers, "Content-Disposition", str);
@@ -251,6 +411,8 @@ content_disposition_changed (GMimeContentDisposition *disposition, gpointer args
        } else {
                g_mime_header_list_remove (object->headers, "Content-Disposition");
        }
+       
+       _g_mime_object_unblock_header_list_changed (object);
 }
 
 
@@ -727,71 +889,10 @@ g_mime_object_get_content_id (GMimeObject *object)
 }
 
 
-enum {
-       HEADER_CONTENT_DISPOSITION,
-       HEADER_CONTENT_TYPE,
-       HEADER_CONTENT_ID,
-       HEADER_UNKNOWN,
-};
-
-static char *content_headers[] = {
-       "Content-Disposition",
-       "Content-Type",
-       "Content-Id",
-};
-
-static gboolean
-process_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, gint64 
offset)
-{
-       GMimeParserOptions *options = _g_mime_header_list_get_options (object->headers);
-       GMimeContentDisposition *disposition;
-       GMimeContentType *content_type;
-       guint i;
-       
-       if (g_ascii_strncasecmp (header, "Content-", 8) != 0)
-               return FALSE;
-       
-       for (i = 0; i < G_N_ELEMENTS (content_headers); i++) {
-               if (!g_ascii_strcasecmp (content_headers[i] + 8, header + 8))
-                       break;
-       }
-       
-       switch (i) {
-       case HEADER_CONTENT_DISPOSITION:
-               disposition = g_mime_content_disposition_parse (options, value);
-               _g_mime_object_set_content_disposition (object, disposition);
-               g_object_unref (disposition);
-               break;
-       case HEADER_CONTENT_TYPE:
-               content_type = g_mime_content_type_parse (options, value);
-               _g_mime_object_set_content_type (object, content_type);
-               g_object_unref (content_type);
-               break;
-       case HEADER_CONTENT_ID:
-               g_free (object->content_id);
-               object->content_id = g_mime_utils_decode_message_id (value);
-               break;
-       default:
-               return FALSE;
-       }
-       
-       _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, 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)
 {
-       GMIME_OBJECT_GET_CLASS (object)->prepend_header (object, header, value, raw_value, offset);
+       _g_mime_header_list_prepend (object->headers, header, value, raw_value, offset);
 }
 
 
@@ -810,24 +911,15 @@ void
 g_mime_object_prepend_header (GMimeObject *object, const char *header, const char *value)
 {
        g_return_if_fail (GMIME_IS_OBJECT (object));
-       g_return_if_fail (header != NULL);
-       g_return_if_fail (value != NULL);
        
-       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, 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);
+       g_mime_header_list_prepend (object->headers, header, value);
 }
 
 
 void
 _g_mime_object_append_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset)
 {
-       GMIME_OBJECT_GET_CLASS (object)->append_header (object, header, value, raw_value, offset);
+       _g_mime_header_list_append (object->headers, header, value, raw_value, offset);
 }
 
 
@@ -846,25 +938,15 @@ void
 g_mime_object_append_header (GMimeObject *object, const char *header, const char *value)
 {
        g_return_if_fail (GMIME_IS_OBJECT (object));
-       g_return_if_fail (header != NULL);
-       g_return_if_fail (value != NULL);
        
-       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, 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);
+       g_mime_header_list_append (object->headers, header, value);
 }
 
 
 void
 _g_mime_object_set_header (GMimeObject *object, const char *header, const char *value, const char 
*raw_value, gint64 offset)
 {
-       GMIME_OBJECT_GET_CLASS (object)->set_header (object, header, value, raw_value, offset);
+       _g_mime_header_list_set (object->headers, header, value, raw_value, offset);
 }
 
 
@@ -883,17 +965,8 @@ void
 g_mime_object_set_header (GMimeObject *object, const char *header, const char *value)
 {
        g_return_if_fail (GMIME_IS_OBJECT (object));
-       g_return_if_fail (header != NULL);
-       g_return_if_fail (value != NULL);
        
-       GMIME_OBJECT_GET_CLASS (object)->set_header (object, header, value, NULL, 0);
-}
-
-
-static const char *
-object_get_header (GMimeObject *object, const char *header)
-{
-       return g_mime_header_list_get (object->headers, header);
+       g_mime_header_list_set (object->headers, header, value);
 }
 
 
@@ -914,42 +987,8 @@ const char *
 g_mime_object_get_header (GMimeObject *object, const char *header)
 {
        g_return_val_if_fail (GMIME_IS_OBJECT (object), NULL);
-       g_return_val_if_fail (header != NULL, NULL);
-       
-       return GMIME_OBJECT_GET_CLASS (object)->get_header (object, header);
-}
-
-
-static gboolean
-object_remove_header (GMimeObject *object, const char *header)
-{
-       guint i;
-       
-       for (i = 0; i < G_N_ELEMENTS (content_headers); i++) {
-               if (!g_ascii_strcasecmp (content_headers[i], header))
-                       break;
-       }
-       
-       switch (i) {
-       case HEADER_CONTENT_DISPOSITION:
-               if (object->disposition) {
-                       g_mime_event_remove (object->disposition->priv, (GMimeEventCallback) 
content_disposition_changed, object);
-                       g_object_unref (object->disposition);
-                       object->disposition = NULL;
-               }
-               break;
-       case HEADER_CONTENT_TYPE:
-               /* never allow the removal of the Content-Type header */
-               return FALSE;
-       case HEADER_CONTENT_ID:
-               g_free (object->content_id);
-               object->content_id = NULL;
-               break;
-       default:
-               break;
-       }
        
-       return g_mime_header_list_remove (object->headers, header);
+       return g_mime_header_list_get (object->headers, header);
 }
 
 
@@ -967,9 +1006,8 @@ gboolean
 g_mime_object_remove_header (GMimeObject *object, const char *header)
 {
        g_return_val_if_fail (GMIME_IS_OBJECT (object), FALSE);
-       g_return_val_if_fail (header != NULL, FALSE);
        
-       return GMIME_OBJECT_GET_CLASS (object)->remove_header (object, header);
+       return g_mime_header_list_remove (object->headers, header);
 }
 
 
diff --git a/gmime/gmime-object.h b/gmime/gmime-object.h
index 81d5f09..fa32286 100644
--- a/gmime/gmime-object.h
+++ b/gmime/gmime-object.h
@@ -67,11 +67,10 @@ struct _GMimeObject {
 struct _GMimeObjectClass {
        GObjectClass parent_class;
        
-       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);
+       void         (* header_added)    (GMimeObject *object, GMimeHeader *header);
+       void         (* header_changed)  (GMimeObject *object, GMimeHeader *header);
+       void         (* header_removed)  (GMimeObject *object, GMimeHeader *header);
+       void         (* headers_cleared) (GMimeObject *object);
        
        void         (* set_content_type) (GMimeObject *object, GMimeContentType *content_type);
        
diff --git a/gmime/gmime-part.c b/gmime/gmime-part.c
index fa14161..91dd1a0 100644
--- a/gmime/gmime-part.c
+++ b/gmime/gmime-part.c
@@ -59,10 +59,11 @@ 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, 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 void mime_part_header_added    (GMimeObject *object, GMimeHeader *header);
+static void mime_part_header_changed  (GMimeObject *object, GMimeHeader *header);
+static void mime_part_header_removed  (GMimeObject *object, GMimeHeader *header);
+static void mime_part_headers_cleared (GMimeObject *object);
+
 static ssize_t mime_part_write_to_stream (GMimeObject *object, GMimeStream *stream, gboolean content_only);
 static void mime_part_encode (GMimeObject *object, GMimeEncodingConstraint constraint);
 
@@ -108,10 +109,10 @@ g_mime_part_class_init (GMimePartClass *klass)
        
        gobject_class->finalize = g_mime_part_finalize;
        
-       object_class->prepend_header = mime_part_prepend_header;
-       object_class->append_header = mime_part_append_header;
-       object_class->remove_header = mime_part_remove_header;
-       object_class->set_header = mime_part_set_header;
+       object_class->header_added = mime_part_header_added;
+       object_class->header_changed = mime_part_header_changed;
+       object_class->header_removed = mime_part_header_removed;
+       object_class->headers_cleared = mime_part_headers_cleared;
        object_class->write_to_stream = mime_part_write_to_stream;
        object_class->encode = mime_part_encode;
        
@@ -177,17 +178,21 @@ copy_atom (const char *src, char *dest, size_t n)
 }
 
 static gboolean
-process_header (GMimeObject *object, const char *header, const char *value)
+process_header (GMimeObject *object, GMimeHeader *header)
 {
        GMimePart *mime_part = (GMimePart *) object;
+       const char *name, *value;
        char encoding[32];
        guint i;
        
-       if (g_ascii_strncasecmp (header, "Content-", 8) != 0)
+       value = g_mime_header_get_value (header);
+       name = g_mime_header_get_name (header);
+       
+       if (g_ascii_strncasecmp (name, "Content-", 8) != 0)
                return FALSE;
        
        for (i = 0; i < G_N_ELEMENTS (content_headers); i++) {
-               if (!g_ascii_strcasecmp (content_headers[i] + 8, header + 8))
+               if (!g_ascii_strcasecmp (content_headers[i] + 8, name + 8))
                        break;
        }
        
@@ -217,41 +222,35 @@ process_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)
+mime_part_header_added (GMimeObject *object, GMimeHeader *header)
 {
-       if (!process_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, raw_value, offset);
+       if (process_header (object, header))
+               return;
+       
+       GMIME_OBJECT_CLASS (parent_class)->header_added (object, header);
 }
 
 static void
-mime_part_append_header (GMimeObject *object, const char *header, const char *value, const char *raw_value, 
gint64 offset)
+mime_part_header_changed (GMimeObject *object, GMimeHeader *header)
 {
-       if (!process_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, raw_value, offset);
+       if (process_header (object, header))
+               return;
+       
+       GMIME_OBJECT_CLASS (parent_class)->header_changed (object, header);
 }
 
 static void
-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, raw_value, offset);
-       else
-               _g_mime_header_list_set (object->headers, header, value, raw_value, offset);
-}
-
-static gboolean
-mime_part_remove_header (GMimeObject *object, const char *header)
+mime_part_header_removed (GMimeObject *object, GMimeHeader *header)
 {
        GMimePart *mime_part = (GMimePart *) object;
+       const char *name;
        guint i;
        
-       if (!g_ascii_strncasecmp (header, "Content-", 8)) {
+       name = g_mime_header_get_name (header);
+       
+       if (!g_ascii_strncasecmp (name, "Content-", 8)) {
                for (i = 0; i < G_N_ELEMENTS (content_headers); i++) {
-                       if (!g_ascii_strcasecmp (content_headers[i] + 8, header + 8))
+                       if (!g_ascii_strcasecmp (content_headers[i] + 8, name + 8))
                                break;
                }
                
@@ -276,9 +275,26 @@ mime_part_remove_header (GMimeObject *object, const char *header)
                }
        }
        
-       return GMIME_OBJECT_CLASS (parent_class)->remove_header (object, header);
+       GMIME_OBJECT_CLASS (parent_class)->header_removed (object, header);
 }
 
+static void
+mime_part_headers_cleared (GMimeObject *object)
+{
+       GMimePart *mime_part = (GMimePart *) object;
+       
+       mime_part->encoding = GMIME_CONTENT_ENCODING_DEFAULT;
+       g_free (mime_part->content_description);
+       mime_part->content_description = NULL;
+       g_free (mime_part->content_location);
+       mime_part->content_location = NULL;
+       g_free (mime_part->content_md5);
+       mime_part->content_md5 = NULL;
+       
+       GMIME_OBJECT_CLASS (parent_class)->headers_cleared (object);
+}
+
+
 static ssize_t
 write_content (GMimePart *part, GMimeStream *stream)
 {
@@ -493,6 +509,8 @@ g_mime_part_new_with_type (const char *type, const char *subtype)
 void
 g_mime_part_set_content_description (GMimePart *mime_part, const char *description)
 {
+       GMimeObject *object = (GMimeObject *) mime_part;
+       
        g_return_if_fail (GMIME_IS_PART (mime_part));
        
        if (mime_part->content_description == description)
@@ -500,7 +518,10 @@ g_mime_part_set_content_description (GMimePart *mime_part, const char *descripti
        
        g_free (mime_part->content_description);
        mime_part->content_description = g_strdup (description);
-       g_mime_header_list_set (GMIME_OBJECT (mime_part)->headers, "Content-Description", description);
+       
+       _g_mime_object_block_header_list_changed (object);
+       g_mime_header_list_set (object->headers, "Content-Description", description);
+       _g_mime_object_unblock_header_list_changed (object);
 }
 
 
@@ -534,7 +555,7 @@ g_mime_part_set_content_id (GMimePart *mime_part, const char *content_id)
 {
        g_return_if_fail (GMIME_IS_PART (mime_part));
        
-       g_mime_object_set_content_id (GMIME_OBJECT (mime_part), content_id);
+       g_mime_object_set_content_id ((GMimeObject *) mime_part, content_id);
 }
 
 
@@ -552,7 +573,7 @@ g_mime_part_get_content_id (GMimePart *mime_part)
 {
        g_return_val_if_fail (GMIME_IS_PART (mime_part), NULL);
        
-       return g_mime_object_get_content_id (GMIME_OBJECT (mime_part));
+       return g_mime_object_get_content_id ((GMimeObject *) mime_part);
 }
 
 
@@ -566,6 +587,7 @@ g_mime_part_get_content_id (GMimePart *mime_part)
 void
 g_mime_part_set_content_md5 (GMimePart *mime_part, const char *content_md5)
 {
+       GMimeObject *object = (GMimeObject *) mime_part;
        unsigned char digest[16], b64digest[32];
        GMimeStreamFilter *filtered_stream;
        GMimeContentType *content_type;
@@ -613,7 +635,10 @@ g_mime_part_set_content_md5 (GMimePart *mime_part, const char *content_md5)
        }
        
        mime_part->content_md5 = g_strdup (content_md5);
-       g_mime_header_list_set (GMIME_OBJECT (mime_part)->headers, "Content-Md5", content_md5);
+       
+       _g_mime_object_block_header_list_changed (object);
+       g_mime_header_list_set (object->headers, "Content-Md5", content_md5);
+       _g_mime_object_unblock_header_list_changed (object);
 }
 
 
@@ -704,6 +729,8 @@ g_mime_part_get_content_md5 (GMimePart *mime_part)
 void
 g_mime_part_set_content_location (GMimePart *mime_part, const char *content_location)
 {
+       GMimeObject *object = (GMimeObject *) mime_part;
+       
        g_return_if_fail (GMIME_IS_PART (mime_part));
        
        if (mime_part->content_location == content_location)
@@ -711,7 +738,10 @@ g_mime_part_set_content_location (GMimePart *mime_part, const char *content_loca
        
        g_free (mime_part->content_location);
        mime_part->content_location = g_strdup (content_location);
-       g_mime_header_list_set (GMIME_OBJECT (mime_part)->headers, "Content-Location", content_location);
+
+       _g_mime_object_block_header_list_changed (object);
+       g_mime_header_list_set (object->headers, "Content-Location", content_location);
+       _g_mime_object_block_header_list_changed (object);
 }
 
 
@@ -743,6 +773,7 @@ g_mime_part_get_content_location (GMimePart *mime_part)
 void
 g_mime_part_set_content_encoding (GMimePart *mime_part, GMimeContentEncoding encoding)
 {
+       GMimeObject *object = (GMimeObject *) mime_part;
        const char *value;
        
        g_return_if_fail (GMIME_IS_PART (mime_part));
@@ -750,7 +781,9 @@ g_mime_part_set_content_encoding (GMimePart *mime_part, GMimeContentEncoding enc
        value = g_mime_content_encoding_to_string (encoding);
        mime_part->encoding = encoding;
        
-       g_mime_header_list_set (GMIME_OBJECT (mime_part)->headers, "Content-Transfer-Encoding", value);
+       _g_mime_object_block_header_list_changed (object);
+       g_mime_header_list_set (object->headers, "Content-Transfer-Encoding", value);
+       _g_mime_object_block_header_list_changed (object);
 }
 
 
diff --git a/tests/test-headers.c b/tests/test-headers.c
index 99310a4..998fa82 100644
--- a/tests/test-headers.c
+++ b/tests/test-headers.c
@@ -364,7 +364,7 @@ test_header_sync (void)
                        throw (exception_new ("address list header unexpectedly null after changing name"));
                
                if (strcmp ("Eva Lucy-Ann Tester <tester localhost com>", value) != 0)
-                       throw (exception_new ("unexpected address list header after changing name"));
+                       throw (exception_new ("unexpected address list header after changing name: %s", 
value));
                
                /* now let's try changing the address mailbox... */
                internet_address_mailbox_set_addr ((InternetAddressMailbox *) addr,
diff --git a/tests/test-parser.c b/tests/test-parser.c
index 2dcf8af..1eba419 100644
--- a/tests/test-parser.c
+++ b/tests/test-parser.c
@@ -38,7 +38,7 @@
 #endif
 
 #define TEST_RAW_HEADER
-//#define TEST_PRESERVE_HEADERS
+#define TEST_PRESERVE_HEADERS
 #define PRINT_MIME_STRUCT
 //#define TEST_WRITE_TO_STREAM
 


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