[gmime] Implemented g_mime_content_type_encode()



commit 0c7fd719a12dcef80960f9508899a103e9b3af2c
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Thu Mar 16 07:35:39 2017 -0400

    Implemented g_mime_content_type_encode()
    
    Renamed g_mime_header_list_get() to g_mime_header_list_get_header()
    and renamed the old g_mime_header_list_get_header() to
    g_mime_header_list_get_header_at().
    
    Also renamed g_mime_content_type_to_string() to
    g_mime_content_type_get_mime_type() and renamed
    g_mime_content_disposition_to_string() to
    g_mime_content_disposition_encode().

 PORTING                           |    4 +
 TODO                              |   10 --
 docs/reference/changes-3.0.sgml   |    2 +
 docs/reference/gmime-sections.txt |   11 ++-
 gmime/gmime-content-type.c        |  177 ++++++++++++++++++++++---------------
 gmime/gmime-content-type.h        |   20 +++--
 gmime/gmime-disposition.c         |   32 ++++----
 gmime/gmime-disposition.h         |    2 +-
 gmime/gmime-header.c              |   41 ++++++---
 gmime/gmime-header.h              |    4 +-
 gmime/gmime-internal.h            |    1 +
 gmime/gmime-message-partial.c     |    2 +-
 gmime/gmime-message.c             |   12 ++--
 gmime/gmime-object.c              |  111 +++++++++++++++--------
 tests/test-headers.c              |   22 +++--
 15 files changed, 271 insertions(+), 180 deletions(-)
---
diff --git a/PORTING b/PORTING
index e8e915f..bf665c2 100644
--- a/PORTING
+++ b/PORTING
@@ -58,9 +58,13 @@ Porting from GMime 2.6 to GMime 3.0
 - g_mime_content_type_new_from_string() has been replaced by
   g_mime_content_type_parse() and now takes a GMimeParserOptions argument.
 
+- g_mime_content_type_to_string() has been replaced by g_mime_content_type_get_mime_type().
+
 - g_mime_content_disposition_new_from_string() has been replaced by
   g_mime_content_disposition_parse() and now takes a GMimeParserOptions argument.
 
+- g_mime_content_disposition_to_string() has been replaced by g_mime_content_disposition_encode().
+
 - internet_address_list_parse_string() has been replaced by
   internet_address_list_parse() and now takes a GMimeParserOptions argument.
 
diff --git a/TODO b/TODO
index 160673e..af43821 100644
--- a/TODO
+++ b/TODO
@@ -12,16 +12,6 @@ GMime 3.0 Planning:
 
 - Rewrite GMimeReferences into a GObject and split into its own file
 
-- Rename g_mime_content_type_to_string() to g_mime_content_type_get_mime_type()
-
-- Add g_mime_content_type_encode()
-
-- Rename g_mime_content_disposition_to_string() to g_mime_content_disposition_encode()
-
-- Fix GMimeObject's content_type_changed() and content_disposition_changed handlers to
-  use the new g_mime_*_encode() functions and update both the value and raw_value of
-  their respective headers.
-
 - Add g_mime_utils_header_decode_[text,phrase]() variants that also return charset/lang values?
 
 
diff --git a/docs/reference/changes-3.0.sgml b/docs/reference/changes-3.0.sgml
index e8aaf48..e422f81 100644
--- a/docs/reference/changes-3.0.sgml
+++ b/docs/reference/changes-3.0.sgml
@@ -42,7 +42,9 @@
       <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_list_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>
+      <listitem><para><function>g_mime_content_type_to_string()</function> has been replaced by 
<function>g_mime_content_type_get_mime_type()</function> and a new function has been introduced called 
<function>g_mime_content_type_encode()</function> that includes the encoded parameter list.</para></listitem>
       <listitem><para><function>g_mime_content_disposition_new_from_string()<function> has been replaced by 
<function>g_mime_content_disposition_parse()</function> and now takes a GMimeParserOptions 
argument.</para></listitem>
+      <listitem><para><function>g_mime_content_disposition_to_string()</function> has been replaced by 
<function>g_mime_content_disposition_encode()</function>.</para></listitem>
       <listitem><para><function>internet_address_list_parse_string()</function> has been replaced by 
<function>internet_address_list_parse()</function> and now takes a GMimeParserOptions 
argument.</para></listitem>
       <listitem><para>GMimeHeaderIter has been dropped in favour of a more direct way of iterating over a 
GMimeHeaderList using int indexes.</para></listitem>
       <listitem><para><function>g_mime_stream_write_to_stream()</function>, 
<function>g_mime_stream_writev()</function>, and <function>g_mime_stream_printf()</function> now return a 
gint64.</para></listitem>
diff --git a/docs/reference/gmime-sections.txt b/docs/reference/gmime-sections.txt
index 840e061..7d6f9c1 100644
--- a/docs/reference/gmime-sections.txt
+++ b/docs/reference/gmime-sections.txt
@@ -603,17 +603,17 @@ g_mime_header_get_value
 g_mime_header_set_value
 g_mime_header_write_to_stream
 g_mime_header_list_new
-g_mime_header_list_destroy
+g_mime_header_list_free
 g_mime_header_list_get_count
 g_mime_header_list_clear
 g_mime_header_list_contains
 g_mime_header_list_get_header
+g_mime_header_list_get_header_at
 g_mime_header_list_prepend
 g_mime_header_list_append
+g_mime_header_list_set
 g_mime_header_list_remove
 g_mime_header_list_remove_at
-g_mime_header_list_set
-g_mime_header_list_get
 g_mime_header_list_register_writer
 g_mime_header_list_write_to_stream
 g_mime_header_list_to_string
@@ -624,7 +624,8 @@ g_mime_header_list_to_string
 GMimeContentType
 g_mime_content_type_new
 g_mime_content_type_parse
-g_mime_content_type_to_string
+g_mime_content_type_get_mime_type
+g_mime_content_type_encode
 g_mime_content_type_is_type
 g_mime_content_type_get_media_type
 g_mime_content_type_set_media_type
@@ -660,7 +661,7 @@ g_mime_content_disposition_get_disposition
 g_mime_content_disposition_get_params
 g_mime_content_disposition_set_parameter
 g_mime_content_disposition_get_parameter
-g_mime_content_disposition_to_string
+g_mime_content_disposition_encode
 
 <SUBSECTION Private>
 g_mime_content_disposition_get_type
diff --git a/gmime/gmime-content-type.c b/gmime/gmime-content-type.c
index 09ea132..89016b6 100644
--- a/gmime/gmime-content-type.c
+++ b/gmime/gmime-content-type.c
@@ -142,36 +142,36 @@ param_list_changed (GMimeParamList *list, gpointer args, GMimeContentType *conte
 GMimeContentType *
 g_mime_content_type_new (const char *type, const char *subtype)
 {
-       GMimeContentType *mime_type;
+       GMimeContentType *content_type;
        
-       mime_type = g_object_newv (GMIME_TYPE_CONTENT_TYPE, 0, NULL);
+       content_type = g_object_newv (GMIME_TYPE_CONTENT_TYPE, 0, NULL);
        
        if (type && *type && subtype && *subtype) {
-               mime_type->type = g_strdup (type);
-               mime_type->subtype = g_strdup (subtype);
+               content_type->type = g_strdup (type);
+               content_type->subtype = g_strdup (subtype);
        } else {
                if (type && *type) {
-                       mime_type->type = g_strdup (type);
+                       content_type->type = g_strdup (type);
                        if (!g_ascii_strcasecmp (type, "text")) {
-                               mime_type->subtype = g_strdup ("plain");
+                               content_type->subtype = g_strdup ("plain");
                        } else if (!g_ascii_strcasecmp (type, "multipart")) {
-                               mime_type->subtype = g_strdup ("mixed");
+                               content_type->subtype = g_strdup ("mixed");
                        } else {
-                               g_free (mime_type->type);
-                               mime_type->type = g_strdup ("application");
-                               mime_type->subtype = g_strdup ("octet-stream");
+                               g_free (content_type->type);
+                               content_type->type = g_strdup ("application");
+                               content_type->subtype = g_strdup ("octet-stream");
                        }
                } else {
-                       mime_type->type = g_strdup ("application");
-                       mime_type->subtype = g_strdup ("octet-stream");
+                       content_type->type = g_strdup ("application");
+                       content_type->subtype = g_strdup ("octet-stream");
                }
                
                w(g_warning ("Invalid or incomplete type: %s%s%s: defaulting to %s/%s",
                             type ? type : "", subtype ? "/" : "", subtype ? subtype : "",
-                            mime_type->type, mime_type->subtype));
+                            content_type->type, content_type->subtype));
        }
        
-       return mime_type;
+       return content_type;
 }
 
 
@@ -187,7 +187,7 @@ g_mime_content_type_new (const char *type, const char *subtype)
 GMimeContentType *
 g_mime_content_type_parse (GMimeParserOptions *options, const char *str)
 {
-       GMimeContentType *mime_type;
+       GMimeContentType *content_type;
        const char *inptr = str;
        GMimeParamList *params;
        char *type, *subtype;
@@ -197,9 +197,9 @@ g_mime_content_type_parse (GMimeParserOptions *options, const char *str)
        if (!g_mime_parse_content_type (&inptr, &type, &subtype))
                return g_mime_content_type_new ("application", "octet-stream");
        
-       mime_type = g_object_newv (GMIME_TYPE_CONTENT_TYPE, 0, NULL);
-       mime_type->subtype = subtype;
-       mime_type->type = type;
+       content_type = g_object_newv (GMIME_TYPE_CONTENT_TYPE, 0, NULL);
+       content_type->subtype = subtype;
+       content_type->type = type;
        
        /* skip past any remaining junk that shouldn't be here... */
        skip_cfws (&inptr);
@@ -207,43 +207,80 @@ g_mime_content_type_parse (GMimeParserOptions *options, const char *str)
                inptr++;
        
        if (*inptr++ == ';' && *inptr && (params = g_mime_param_list_parse (options, inptr))) {
-               g_mime_event_add (params->changed, (GMimeEventCallback) param_list_changed, mime_type);
-               g_mime_param_list_free (mime_type->params);
-               mime_type->params = params;
+               g_mime_event_add (params->changed, (GMimeEventCallback) param_list_changed, content_type);
+               g_mime_param_list_free (content_type->params);
+               content_type->params = params;
        }
        
-       return mime_type;
+       return content_type;
 }
 
 
 /**
- * g_mime_content_type_to_string:
- * @mime_type: a #GMimeContentType object
+ * g_mime_content_type_get_mime_type:
+ * @content_type: a #GMimeContentType
  *
  * Allocates a string buffer containing the type and subtype defined
- * by the @mime_type.
+ * by the @content_type.
  *
  * Returns: an allocated string containing the type and subtype of the
  * content-type in the format: type/subtype.
  **/
 char *
-g_mime_content_type_to_string (GMimeContentType *mime_type)
+g_mime_content_type_get_mime_type (GMimeContentType *content_type)
 {
-       char *string;
+       char *mime_type;
        
-       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), NULL);
+       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (content_type), NULL);
        
        /* type and subtype should never be NULL, but check anyway */
-       string = g_strdup_printf ("%s/%s", mime_type->type ? mime_type->type : "text",
-                                 mime_type->subtype ? mime_type->subtype : "plain");
+       mime_type = g_strdup_printf ("%s/%s", content_type->type ? content_type->type : "text",
+                                    content_type->subtype ? content_type->subtype : "plain");
        
-       return string;
+       return mime_type;
+}
+
+
+/**
+ * g_mime_content_type_encode:
+ * @content_type: a #GMimeContentType
+ *
+ * Encodes the Content-Disposition header.
+ *
+ * Returns: a new string containing the encoded header value.
+ **/
+char *
+g_mime_content_type_encode (GMimeContentType *content_type)
+{
+       char *raw_value;
+       GString *str;
+       guint len, n;
+       
+       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (content_type), NULL);
+       
+       /* we need to have this so wrapping is correct */
+       str = g_string_new ("Content-Type:");
+       n = str->len;
+       
+       g_string_append_c (str, ' ');
+       g_string_append (str, content_type->type ? content_type->type : "text");
+       g_string_append_c (str, '/');
+       g_string_append (str, content_type->subtype ? content_type->subtype : "plain");
+       
+       g_mime_param_list_encode (content_type->params, TRUE, str);
+       len = str->len - n;
+       
+       raw_value = g_string_free (str, FALSE);
+       
+       memmove (raw_value, raw_value + n, len + 1);
+       
+       return raw_value;
 }
 
 
 /**
  * g_mime_content_type_is_type:
- * @mime_type: a #GMimeContentType object
+ * @content_type: a #GMimeContentType
  * @type: MIME type to compare against
  * @subtype: MIME subtype to compare against
  *
@@ -254,21 +291,21 @@ g_mime_content_type_to_string (GMimeContentType *mime_type)
  * use "*" in place of @type and/or @subtype as a wilcard.
  **/
 gboolean
-g_mime_content_type_is_type (GMimeContentType *mime_type, const char *type, const char *subtype)
+g_mime_content_type_is_type (GMimeContentType *content_type, const char *type, const char *subtype)
 {
-       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), FALSE);
-       g_return_val_if_fail (mime_type->type != NULL, FALSE);
-       g_return_val_if_fail (mime_type->subtype != NULL, FALSE);
+       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (content_type), FALSE);
+       g_return_val_if_fail (content_type->type != NULL, FALSE);
+       g_return_val_if_fail (content_type->subtype != NULL, FALSE);
        g_return_val_if_fail (type != NULL, FALSE);
        g_return_val_if_fail (subtype != NULL, FALSE);
        
-       if (!strcmp (type, "*") || !g_ascii_strcasecmp (mime_type->type, type)) {
+       if (!strcmp (type, "*") || !g_ascii_strcasecmp (content_type->type, type)) {
                if (!strcmp (subtype, "*")) {
                        /* special case */
                        return TRUE;
                }
                
-               if (!g_ascii_strcasecmp (mime_type->subtype, subtype))
+               if (!g_ascii_strcasecmp (content_type->subtype, subtype))
                        return TRUE;
        }
        
@@ -278,104 +315,104 @@ g_mime_content_type_is_type (GMimeContentType *mime_type, const char *type, cons
 
 /**
  * g_mime_content_type_set_media_type:
- * @mime_type: a #GMimeContentType object
+ * @content_type: a #GMimeContentType
  * @type: media type
  *
  * Sets the Content-Type's media type.
  **/
 void
-g_mime_content_type_set_media_type (GMimeContentType *mime_type, const char *type)
+g_mime_content_type_set_media_type (GMimeContentType *content_type, const char *type)
 {
        char *buf;
        
-       g_return_if_fail (GMIME_IS_CONTENT_TYPE (mime_type));
+       g_return_if_fail (GMIME_IS_CONTENT_TYPE (content_type));
        g_return_if_fail (type != NULL);
        
        buf = g_strdup (type);
-       g_free (mime_type->type);
-       mime_type->type = buf;
+       g_free (content_type->type);
+       content_type->type = buf;
        
-       g_mime_event_emit (mime_type->changed, NULL);
+       g_mime_event_emit (content_type->changed, NULL);
 }
 
 
 /**
  * g_mime_content_type_get_media_type:
- * @mime_type: a #GMimeContentType object
+ * @content_type: a #GMimeContentType
  *
  * Gets the Content-Type's media type.
  *
  * Returns: the Content-Type's media type.
  **/
 const char *
-g_mime_content_type_get_media_type (GMimeContentType *mime_type)
+g_mime_content_type_get_media_type (GMimeContentType *content_type)
 {
-       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), NULL);
+       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (content_type), NULL);
        
-       return mime_type->type;
+       return content_type->type;
 }
 
 
 /**
  * g_mime_content_type_set_media_subtype:
- * @mime_type: a #GMimeContentType object
+ * @content_type: a #GMimeContentType
  * @subtype: media subtype
  *
  * Sets the Content-Type's media subtype.
  **/
 void
-g_mime_content_type_set_media_subtype (GMimeContentType *mime_type, const char *subtype)
+g_mime_content_type_set_media_subtype (GMimeContentType *content_type, const char *subtype)
 {
        char *buf;
        
-       g_return_if_fail (GMIME_IS_CONTENT_TYPE (mime_type));
+       g_return_if_fail (GMIME_IS_CONTENT_TYPE (content_type));
        g_return_if_fail (subtype != NULL);
        
        buf = g_strdup (subtype);
-       g_free (mime_type->subtype);
-       mime_type->subtype = buf;
+       g_free (content_type->subtype);
+       content_type->subtype = buf;
        
-       g_mime_event_emit (mime_type->changed, NULL);
+       g_mime_event_emit (content_type->changed, NULL);
 }
 
 
 /**
  * g_mime_content_type_get_media_subtype:
- * @mime_type: a #GMimeContentType object
+ * @content_type: a #GMimeContentType
  *
  * Gets the Content-Type's media sub-type.
  *
  * Returns: the Content-Type's media sub-type.
  **/
 const char *
-g_mime_content_type_get_media_subtype (GMimeContentType *mime_type)
+g_mime_content_type_get_media_subtype (GMimeContentType *content_type)
 {
-       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), NULL);
+       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (content_type), NULL);
        
-       return mime_type->subtype;
+       return content_type->subtype;
 }
 
 
 /**
  * g_mime_content_type_get_params:
- * @mime_type: a #GMimeContentType object
+ * @content_type: a #GMimeContentType
  *
  * Gets the Content-Type's parameter list.
  *
  * Returns: the Content-Type's parameter list.
  **/
 GMimeParamList *
-g_mime_content_type_get_params (GMimeContentType *mime_type)
+g_mime_content_type_get_params (GMimeContentType *content_type)
 {
-       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), NULL);
+       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (content_type), NULL);
        
-       return mime_type->params;
+       return content_type->params;
 }
 
 
 /**
  * g_mime_content_type_set_parameter:
- * @mime_type: MIME Content-Type
+ * @content_type: a #GMimeContentType
  * @name: parameter name (aka attribute)
  * @value: parameter value
  *
@@ -385,17 +422,17 @@ g_mime_content_type_get_params (GMimeContentType *mime_type)
  * UTF-8.
  **/
 void
-g_mime_content_type_set_parameter (GMimeContentType *mime_type, const char *name, const char *value)
+g_mime_content_type_set_parameter (GMimeContentType *content_type, const char *name, const char *value)
 {
-       g_return_if_fail (GMIME_IS_CONTENT_TYPE (mime_type));
+       g_return_if_fail (GMIME_IS_CONTENT_TYPE (content_type));
        
-       g_mime_param_list_set_parameter (mime_type->params, name, value);
+       g_mime_param_list_set_parameter (content_type->params, name, value);
 }
 
 
 /**
  * g_mime_content_type_get_parameter:
- * @mime_type: a #GMimeContentType object
+ * @content_type: a #GMimeContentType
  * @name: parameter name (aka attribute)
  *
  * Gets the parameter value specified by @name if it's available.
@@ -405,13 +442,13 @@ g_mime_content_type_set_parameter (GMimeContentType *mime_type, const char *name
  * will be in UTF-8.
  **/
 const char *
-g_mime_content_type_get_parameter (GMimeContentType *mime_type, const char *name)
+g_mime_content_type_get_parameter (GMimeContentType *content_type, const char *name)
 {
        GMimeParam *param;
        
-       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (mime_type), NULL);
+       g_return_val_if_fail (GMIME_IS_CONTENT_TYPE (content_type), NULL);
        
-       if (!(param = g_mime_param_list_get_parameter (mime_type->params, name)))
+       if (!(param = g_mime_param_list_get_parameter (content_type->params, name)))
                return NULL;
        
        return param->value;
diff --git a/gmime/gmime-content-type.h b/gmime/gmime-content-type.h
index eb6cb4c..67a91ef 100644
--- a/gmime/gmime-content-type.h
+++ b/gmime/gmime-content-type.h
@@ -68,20 +68,22 @@ GType g_mime_content_type_get_type (void);
 GMimeContentType *g_mime_content_type_new (const char *type, const char *subtype);
 GMimeContentType *g_mime_content_type_parse (GMimeParserOptions *options, const char *str);
 
-char *g_mime_content_type_to_string (GMimeContentType *mime_type);
+char *g_mime_content_type_get_mime_type (GMimeContentType *content_type);
 
-gboolean g_mime_content_type_is_type (GMimeContentType *mime_type, const char *type, const char *subtype);
+char *g_mime_content_type_encode (GMimeContentType *content_type);
 
-void g_mime_content_type_set_media_type (GMimeContentType *mime_type, const char *type);
-const char *g_mime_content_type_get_media_type (GMimeContentType *mime_type);
+gboolean g_mime_content_type_is_type (GMimeContentType *content_type, const char *type, const char *subtype);
 
-void g_mime_content_type_set_media_subtype (GMimeContentType *mime_type, const char *subtype);
-const char *g_mime_content_type_get_media_subtype (GMimeContentType *mime_type);
+void g_mime_content_type_set_media_type (GMimeContentType *content_type, const char *type);
+const char *g_mime_content_type_get_media_type (GMimeContentType *content_type);
 
-GMimeParamList *g_mime_content_type_get_params (GMimeContentType *mime_type);
+void g_mime_content_type_set_media_subtype (GMimeContentType *content_type, const char *subtype);
+const char *g_mime_content_type_get_media_subtype (GMimeContentType *content_type);
 
-void g_mime_content_type_set_parameter (GMimeContentType *mime_type, const char *name, const char *value);
-const char *g_mime_content_type_get_parameter (GMimeContentType *mime_type, const char *name);
+GMimeParamList *g_mime_content_type_get_params (GMimeContentType *content_type);
+
+void g_mime_content_type_set_parameter (GMimeContentType *content_type, const char *name, const char *value);
+const char *g_mime_content_type_get_parameter (GMimeContentType *content_type, const char *name);
 
 G_END_DECLS
 
diff --git a/gmime/gmime-disposition.c b/gmime/gmime-disposition.c
index db03d57..85e1fd5 100644
--- a/gmime/gmime-disposition.c
+++ b/gmime/gmime-disposition.c
@@ -304,34 +304,34 @@ g_mime_content_disposition_is_attachment (GMimeContentDisposition *disposition)
 
 
 /**
- * g_mime_content_disposition_to_string:
+ * g_mime_content_disposition_encode:
  * @disposition: a #GMimeContentDisposition object
- * @fold: fold header if needed
  *
- * Allocates a string buffer containing the Content-Disposition header
- * represented by the disposition object @disposition.
+ * Encodes the Content-Disposition header.
  *
- * Returns: a string containing the disposition header
+ * Returns: a new string containing the encoded header value.
  **/
 char *
-g_mime_content_disposition_to_string (GMimeContentDisposition *disposition, gboolean fold)
+g_mime_content_disposition_encode (GMimeContentDisposition *disposition)
 {
-       char *header, *buf;
-       GString *string;
+       char *raw_value;
+       GString *str;
+       guint len, n;
        
        g_return_val_if_fail (GMIME_IS_CONTENT_DISPOSITION (disposition), NULL);
        
        /* we need to have this so wrapping is correct */
-       string = g_string_new ("Content-Disposition: ");
+       str = g_string_new ("Content-Disposition:");
+       n = str->len;
        
-       g_string_append (string, disposition->disposition);
-       g_mime_param_list_encode (disposition->params, fold, string);
+       g_string_append_c (str, ' ');
+       g_string_append (str, disposition->disposition);
+       g_mime_param_list_encode (disposition->params, TRUE, str);
+       len = str->len - n;
        
-       header = string->str;
-       g_string_free (string, FALSE);
+       raw_value = g_string_free (str, FALSE);
        
-       buf = header + strlen ("Content-Disposition: ");
-       memmove (header, buf, strlen (buf) + 1);
+       memmove (raw_value, raw_value + n, len + 1);
        
-       return header;
+       return raw_value;
 }
diff --git a/gmime/gmime-disposition.h b/gmime/gmime-disposition.h
index e5586b2..3e55c33 100644
--- a/gmime/gmime-disposition.h
+++ b/gmime/gmime-disposition.h
@@ -96,7 +96,7 @@ const char *g_mime_content_disposition_get_parameter (GMimeContentDisposition *d
 
 gboolean g_mime_content_disposition_is_attachment (GMimeContentDisposition *disposition);
 
-char *g_mime_content_disposition_to_string (GMimeContentDisposition *disposition, gboolean fold);
+char *g_mime_content_disposition_encode (GMimeContentDisposition *disposition);
 
 G_END_DECLS
 
diff --git a/gmime/gmime-header.c b/gmime/gmime-header.c
index b4428f0..8b26153 100644
--- a/gmime/gmime-header.c
+++ b/gmime/gmime-header.c
@@ -192,6 +192,25 @@ _g_mime_header_get_raw_value (GMimeHeader *header)
 
 
 /**
+ * g_mime_header_set_raw_value:
+ * @header: a #GMimeHeader
+ * @raw_value: the raw value
+ *
+ * Sets the header's raw value.
+ **/
+void
+_g_mime_header_set_raw_value (GMimeHeader *header, const char *raw_value)
+{
+       g_return_if_fail (header != NULL);
+       g_return_if_fail (raw_value != NULL);
+       
+       g_free (header->raw_value);
+       
+       header->raw_value = g_strdup (raw_value);
+}
+
+
+/**
  * g_mime_header_get_offset:
  * @header: a #GMimeHeader
  *
@@ -519,29 +538,23 @@ g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const cha
 
 
 /**
- * g_mime_header_list_get:
+ * g_mime_header_list_get_header:
  * @headers: a #GMimeHeaderList
  * @name: header name
  *
- * Gets the value of the first header with the specified name.
- *
- * Returns: the value of the header requested.
+ * Gets the first header with the specified name.
  *
- * Note: The returned value should be decoded with a function such as
- * g_mime_utils_header_decode_text() before displaying to the user.
+ * Returns: a #GMimeHeader for the specified @name.
  **/
-const char *
-g_mime_header_list_get (GMimeHeaderList *headers, const char *name)
+GMimeHeader *
+g_mime_header_list_get_header (GMimeHeaderList *headers, const char *name)
 {
        GMimeHeader *header;
        
        g_return_val_if_fail (headers != NULL, NULL);
        g_return_val_if_fail (name != NULL, NULL);
        
-       if (!(header = g_hash_table_lookup (headers->hash, name)))
-               return NULL;
-       
-       return header->value;
+       return g_hash_table_lookup (headers->hash, name);
 }
 
 
@@ -613,7 +626,7 @@ g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *
 
 
 /**
- * g_mime_header_list_get_header:
+ * g_mime_header_list_get_header_at:
  * @headers: a #GMimeHeaderList
  * @index: the 0-based index of the header
  *
@@ -622,7 +635,7 @@ g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *
  * Returns: (transfer none): the header at position @index.
  **/
 GMimeHeader *
-g_mime_header_list_get_header (GMimeHeaderList *headers, int index)
+g_mime_header_list_get_header_at (GMimeHeaderList *headers, int index)
 {
        g_return_val_if_fail (headers != NULL, NULL);
        g_return_val_if_fail (index >= 0, NULL);
diff --git a/gmime/gmime-header.h b/gmime/gmime-header.h
index 8d29669..2827a13 100644
--- a/gmime/gmime-header.h
+++ b/gmime/gmime-header.h
@@ -77,8 +77,8 @@ gboolean g_mime_header_list_contains (GMimeHeaderList *headers, const char *name
 void g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char *value);
 void g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char *value);
 void g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value);
-const char *g_mime_header_list_get (GMimeHeaderList *headers, const char *name);
-GMimeHeader *g_mime_header_list_get_header (GMimeHeaderList *headers, int index);
+GMimeHeader *g_mime_header_list_get_header (GMimeHeaderList *headers, const char *name);
+GMimeHeader *g_mime_header_list_get_header_at (GMimeHeaderList *headers, int index);
 gboolean g_mime_header_list_remove (GMimeHeaderList *headers, const char *name);
 void g_mime_header_list_remove_at (GMimeHeaderList *headers, int index);
 
diff --git a/gmime/gmime-internal.h b/gmime/gmime-internal.h
index 5d184a4..9fe0ef5 100644
--- a/gmime/gmime-internal.h
+++ b/gmime/gmime-internal.h
@@ -48,6 +48,7 @@ G_GNUC_INTERNAL GMimeParserOptions *_g_mime_parser_options_clone (GMimeParserOpt
 
 /* GMimeHeader */
 G_GNUC_INTERNAL const char *_g_mime_header_get_raw_value (GMimeHeader *header);
+G_GNUC_INTERNAL void _g_mime_header_set_raw_value (GMimeHeader *header, const char *raw_value);
 G_GNUC_INTERNAL void _g_mime_header_set_offset (GMimeHeader *header, gint64 offset);
 
 /* GMimeHeaderList */
diff --git a/gmime/gmime-message-partial.c b/gmime/gmime-message-partial.c
index c1deacd..d7076bd 100644
--- a/gmime/gmime-message-partial.c
+++ b/gmime/gmime-message-partial.c
@@ -335,7 +335,7 @@ message_partial_message_new (GMimeMessage *base)
        count = g_mime_header_list_get_count (headers);
        
        for (i = 0; i < count; i++) {
-               header = g_mime_header_list_get_header (headers, i);
+               header = g_mime_header_list_get_header_at (headers, i);
                raw_value = _g_mime_header_get_raw_value (header);
                offset = g_mime_header_get_offset (header);
                value = g_mime_header_get_value (header);
diff --git a/gmime/gmime-message.c b/gmime/gmime-message.c
index 8438a65..3eaeaaa 100644
--- a/gmime/gmime-message.c
+++ b/gmime/gmime-message.c
@@ -674,7 +674,7 @@ message_update_addresses (GMimeMessage *message, GMimeParserOptions *options, GM
        
        count = g_mime_header_list_get_count (headers);
        for (i = 0; i < count; i++) {
-               header = g_mime_header_list_get_header (headers, i);
+               header = g_mime_header_list_get_header_at (headers, i);
                name = g_mime_header_get_name (header);
                
                if (g_ascii_strcasecmp (address_types[type].name, name) != 0)
@@ -861,11 +861,11 @@ write_headers_to_stream (GMimeObject *object, GMimeStream *stream)
                int index = 0;
                
                while (index < count && body_index < body_count) {
-                       body_header = g_mime_header_list_get_header (mime_part->headers, body_index);
+                       body_header = g_mime_header_list_get_header_at (mime_part->headers, body_index);
                        if ((body_offset = g_mime_header_get_offset (body_header)) < 0)
                                break;
                        
-                       header = g_mime_header_list_get_header (object->headers, index);
+                       header = g_mime_header_list_get_header_at (object->headers, index);
                        offset = g_mime_header_get_offset (header);
                        
                        if (offset >= 0 && offset < body_offset) {
@@ -884,7 +884,7 @@ write_headers_to_stream (GMimeObject *object, GMimeStream *stream)
                }
                
                while (index < count) {
-                       header = g_mime_header_list_get_header (object->headers, index);
+                       header = g_mime_header_list_get_header_at (object->headers, index);
                        
                        if ((nwritten = g_mime_header_write_to_stream (header, stream)) == -1)
                                return -1;
@@ -894,7 +894,7 @@ write_headers_to_stream (GMimeObject *object, GMimeStream *stream)
                }
                
                while (body_index < body_count) {
-                       header = g_mime_header_list_get_header (mime_part->headers, body_index);
+                       header = g_mime_header_list_get_header_at (mime_part->headers, body_index);
                        
                        if ((nwritten = g_mime_header_write_to_stream (header, stream)) == -1)
                                return -1;
@@ -1473,7 +1473,7 @@ g_mime_message_set_mime_part (GMimeMessage *message, GMimeObject *mime_part)
                        g_mime_header_list_append (headers, "MIME-Version", "1.0");
                
                for (i = 0; i < g_mime_header_list_get_count (mime_part->headers); i++) {
-                       header = g_mime_header_list_get_header (mime_part->headers, i);
+                       header = g_mime_header_list_get_header_at (mime_part->headers, i);
                        _g_mime_header_set_offset (header, -1);
                }
                
diff --git a/gmime/gmime-object.c b/gmime/gmime-object.c
index 57e579c..2d6a77d 100644
--- a/gmime/gmime-object.c
+++ b/gmime/gmime-object.c
@@ -310,23 +310,21 @@ write_content_type (GMimeParserOptions *options, GMimeStream *stream, const char
 {
        GMimeContentType *content_type;
        ssize_t nwritten;
-       GString *out;
-       char *val;
+       char *raw_value;
+       GString *str;
        
-       out = g_string_new ("");
-       g_string_printf (out, "%s: ", name);
+       str = g_string_new (name);
+       g_string_append_c (str, ':');
        
        content_type = g_mime_content_type_parse (options, value);
-       
-       val = g_mime_content_type_to_string (content_type);
-       g_string_append (out, val);
-       g_free (val);
-       
-       g_mime_param_list_encode (content_type->params, TRUE, out);
+       raw_value = g_mime_content_type_encode (content_type);
        g_object_unref (content_type);
        
-       nwritten = g_mime_stream_write (stream, out->str, out->len);
-       g_string_free (out, TRUE);
+       g_string_append (str, raw_value);
+       g_free (raw_value);
+       
+       nwritten = g_mime_stream_write (stream, str->str, str->len);
+       g_string_free (str, TRUE);
        
        return nwritten;
 }
@@ -349,27 +347,52 @@ _g_mime_object_unblock_header_list_changed (GMimeObject *object)
        g_mime_event_unblock (event, (GMimeEventCallback) header_list_changed, object);
 }
 
-static void
-content_type_changed (GMimeContentType *content_type, gpointer args, GMimeObject *object)
+static char *
+unfold_raw_value (const char *raw_value)
 {
-       GString *string;
-       char *type, *str;
-       
-       string = g_string_new ("Content-Type: ");
+       char *value = g_malloc (strlen (raw_value) + 1);
+       register const char *inptr = raw_value;
+       register char *outptr = value;
+       
+       while (*inptr) {
+               if (*inptr == '\n') {
+                       inptr++;
+                       
+                       if (*inptr == '\0')
+                               break;
+                       
+                       if (*inptr == '\t') {
+                               *outptr++ = ' ';
+                               inptr++;
+                       } else {
+                               *outptr++ = *inptr++;
+                       }
+               } else {
+                       *outptr++ = *inptr++;
+               }
+       }
        
-       type = g_mime_content_type_to_string (content_type);
-       g_string_append (string, type);
-       g_free (type);
+       *outptr = '\0';
        
-       g_mime_param_list_encode (content_type->params, FALSE, string);
+       return value;
+}
+
+static void
+content_type_changed (GMimeContentType *content_type, gpointer args, GMimeObject *object)
+{
+       char *raw_value, *value;
+       GMimeHeader *header;
        
-       str = g_string_free (string, FALSE);
+       raw_value = g_mime_content_type_encode (content_type);
+       value = unfold_raw_value (raw_value);
        
-       type = str + strlen ("Content-Type: ");
        _g_mime_object_block_header_list_changed (object);
-       g_mime_header_list_set (object->headers, "Content-Type", type);
+       g_mime_header_list_set (object->headers, "Content-Type", value);
+       header = g_mime_header_list_get_header (object->headers, "Content-Type");
+       _g_mime_header_set_raw_value (header, raw_value);
        _g_mime_object_unblock_header_list_changed (object);
-       g_free (str);
+       g_free (raw_value);
+       g_free (value);
 }
 
 static ssize_t
@@ -377,19 +400,20 @@ write_disposition (GMimeParserOptions *options, GMimeStream *stream, const char
 {
        GMimeContentDisposition *disposition;
        ssize_t nwritten;
-       GString *out;
+       char *raw_value;
+       GString *str;
        
-       out = g_string_new ("");
-       g_string_printf (out, "%s: ", name);
+       str = g_string_new (name);
+       g_string_append_c (str, ':');
        
        disposition = g_mime_content_disposition_parse (options, value);
-       g_string_append (out, disposition->disposition);
+       g_string_append (str, disposition->disposition);
        
-       g_mime_param_list_encode (disposition->params, TRUE, out);
+       g_mime_param_list_encode (disposition->params, TRUE, str);
        g_object_unref (disposition);
        
-       nwritten = g_mime_stream_write (stream, out->str, out->len);
-       g_string_free (out, TRUE);
+       nwritten = g_mime_stream_write (stream, str->str, str->len);
+       g_string_free (str, TRUE);
        
        return nwritten;
 }
@@ -397,14 +421,20 @@ write_disposition (GMimeParserOptions *options, GMimeStream *stream, const char
 static void
 content_disposition_changed (GMimeContentDisposition *disposition, gpointer args, GMimeObject *object)
 {
-       char *str;
+       char *raw_value, *value;
+       GMimeHeader *header;
        
        _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);
-               g_free (str);
+               raw_value = g_mime_content_disposition_encode (object->disposition);
+               value = unfold_raw_value (raw_value);
+               
+               g_mime_header_list_set (object->headers, "Content-Disposition", value);
+               header = g_mime_header_list_get_header (object->headers, "Content-Disposition");
+               _g_mime_header_set_raw_value (header, raw_value);
+               g_free (raw_value);
+               g_free (value);
        } else {
                g_mime_header_list_remove (object->headers, "Content-Disposition");
        }
@@ -985,9 +1015,14 @@ g_mime_object_set_header (GMimeObject *object, const char *header, const char *v
 const char *
 g_mime_object_get_header (GMimeObject *object, const char *header)
 {
+       GMimeHeader *hdr;
+       
        g_return_val_if_fail (GMIME_IS_OBJECT (object), NULL);
        
-       return g_mime_header_list_get (object->headers, header);
+       if (!(hdr = g_mime_header_list_get_header (object->headers, header)))
+               return NULL;
+       
+       return g_mime_header_get_value (hdr);
 }
 
 
diff --git a/tests/test-headers.c b/tests/test-headers.c
index 7dbb9fb..b566619 100644
--- a/tests/test-headers.c
+++ b/tests/test-headers.c
@@ -81,7 +81,7 @@ test_indexing (void)
        for (index = 0; index < G_N_ELEMENTS (initial); index++) {
                testsuite_check ("headers[%d]", index);
                try {
-                       if (!(header = g_mime_header_list_get_header (list, index)))
+                       if (!(header = g_mime_header_list_get_header_at (list, index)))
                                throw (exception_new ("failed to get header at index"));
                        
                        name = g_mime_header_get_name (header);
@@ -99,7 +99,7 @@ test_indexing (void)
        /* make sure trying to advance past the last header fails */
        testsuite_check ("indexing past end of headers");
        try {
-               if (g_mime_header_list_get_header (list, index) != NULL)
+               if (g_mime_header_list_get_header_at (list, index) != NULL)
                        throw (exception_new ("should not have worked"));
                testsuite_check_passed ();
        } catch (ex) {
@@ -126,7 +126,7 @@ test_remove (void)
                        throw (exception_new ("failed to remove header"));
                
                /* make sure the first header is now the same as the second original header */
-               header = g_mime_header_list_get_header (list, 0);
+               header = g_mime_header_list_get_header_at (list, 0);
                name = g_mime_header_get_name (header);
                value = g_mime_header_get_value (header);
                
@@ -135,9 +135,12 @@ test_remove (void)
                        throw (exception_new ("expected second Received header"));
                
                /* make sure that the internal hash table was properly updated */
-               if (!(value = g_mime_header_list_get (list, "Received")))
+               if (!(header = g_mime_header_list_get_header (list, "Received")))
                        throw (exception_new ("lookup of Received header failed"));
                
+               if (!(value = g_mime_header_get_value (header)))
+                       throw (exception_new ("getting Received header value failed"));
+               
                if (strcmp (initial[1].value, value) != 0)
                        throw (exception_new ("expected second Received header value"));
                
@@ -151,7 +154,7 @@ test_remove (void)
                /* remove the last header */
                g_mime_header_list_remove (list, "Message-Id");
                
-               if ((value = g_mime_header_list_get (list, "Message-Id")) != NULL)
+               if ((header = g_mime_header_list_get_header (list, "Message-Id")) != NULL)
                        throw (exception_new ("lookup of Message-Id should have failed"));
                
                testsuite_check_passed ();
@@ -179,7 +182,7 @@ test_remove_at (void)
                g_mime_header_list_remove_at (list, 0);
                
                /* make sure the first header is now the same as the second original header */
-               header = g_mime_header_list_get_header (list, 0);
+               header = g_mime_header_list_get_header_at (list, 0);
                name = g_mime_header_get_name (header);
                value = g_mime_header_get_value (header);
                
@@ -188,9 +191,12 @@ test_remove_at (void)
                        throw (exception_new ("expected second Received header"));
                
                /* make sure that the internal hash table was properly updated */
-               if (!(value = g_mime_header_list_get (list, "Received")))
+               if (!(header = g_mime_header_list_get_header (list, "Received")))
                        throw (exception_new ("lookup of Received header failed"));
                
+               if (!(value = g_mime_header_get_value (header)))
+                       throw (exception_new ("getting Received header value failed"));
+               
                if (strcmp (initial[1].value, value) != 0)
                        throw (exception_new ("expected second Received header value"));
                
@@ -205,7 +211,7 @@ test_remove_at (void)
                count = g_mime_header_list_get_count (list);
                g_mime_header_list_remove_at (list, count - 1);
                
-               if ((value = g_mime_header_list_get (list, "Message-Id")) != NULL)
+               if ((header = g_mime_header_list_get_header (list, "Message-Id")) != NULL)
                        throw (exception_new ("lookup of Message-Id should have failed"));
                
                testsuite_check_passed ();



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