[gmime: 16/21] Directly set the raw values when InternetAddress/ContentType/Disposition change



commit cb1ff4d07f487527e073cf5317069289ebfa5c26
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Sun Mar 26 08:14:08 2017 -0400

    Directly set the raw values when InternetAddress/ContentType/Disposition change

 gmime/gmime-header.c     |   68 +++++++++++++++++++++++++++++++++---
 gmime/gmime-header.h     |    1 +
 gmime/gmime-internal.h   |    1 +
 gmime/gmime-message.c    |   15 +++++---
 gmime/gmime-object.c     |   61 ++++-----------------------------
 gmime/internet-address.c |   86 +++++++++++++++++++++++++---------------------
 gmime/internet-address.h |    5 +--
 7 files changed, 131 insertions(+), 106 deletions(-)
---
diff --git a/gmime/gmime-header.c b/gmime/gmime-header.c
index 039e17b..b2f7b8c 100644
--- a/gmime/gmime-header.c
+++ b/gmime/gmime-header.c
@@ -333,6 +333,19 @@ g_mime_header_get_raw_value (GMimeHeader *header)
 }
 
 
+void
+_g_mime_header_set_raw_value (GMimeHeader *header, const char *raw_value)
+{
+       char *buf = g_strdup (raw_value);
+       
+       g_free (header->raw_value);
+       g_free (header->value);
+       
+       header->raw_value = buf;
+       header->value = NULL;
+}
+
+
 /**
  * g_mime_header_set_raw_value:
  * @header: a #GMimeHeader
@@ -341,13 +354,21 @@ g_mime_header_get_raw_value (GMimeHeader *header)
  * Sets the header's raw value.
  **/
 void
-_g_mime_header_set_raw_value (GMimeHeader *header, const char *raw_value)
+g_mime_header_set_raw_value (GMimeHeader *header, const char *raw_value)
 {
-       //g_return_if_fail (GMIME_IS_HEADER (header));
-       //g_return_if_fail (raw_value != NULL);
+       char *buf;
        
+       g_return_if_fail (GMIME_IS_HEADER (header));
+       g_return_if_fail (raw_value != NULL);
+       
+       buf = g_strdup (raw_value);
        g_free (header->raw_value);
-       header->raw_value = g_strdup (raw_value);
+       g_free (header->value);
+       
+       header->raw_value = buf;
+       header->value = NULL;
+       
+       g_mime_event_emit (header->changed, NULL);
 }
 
 
@@ -533,7 +554,7 @@ g_mime_header_format_addrlist (GMimeHeader *header, GMimeFormatOptions *options,
        g_string_append_c (str, ' ');
        
        if (value && (addrlist = internet_address_list_parse (header->options, value))) {
-               internet_address_list_writer (addrlist, options, str);
+               internet_address_list_encode (addrlist, options, str);
                g_object_unref (addrlist);
        }
        
@@ -1154,6 +1175,43 @@ g_mime_header_list_get_header (GMimeHeaderList *headers, const char *name)
 }
 
 
+void
+_g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *raw_value)
+{
+       GMimeHeaderListChangedEventArgs args;
+       GMimeHeader *header, *hdr;
+       guint i;
+       
+       g_return_if_fail (GMIME_IS_HEADER_LIST (headers));
+       g_return_if_fail (name != NULL);
+       
+       if ((header = g_hash_table_lookup (headers->hash, name))) {
+               g_mime_header_set_raw_value (header, raw_value);
+               
+               for (i = headers->array->len - 1; i > 0; i--) {
+                       hdr = (GMimeHeader *) headers->array->pdata[i];
+                       
+                       if (hdr == header)
+                               break;
+                       
+                       if (g_ascii_strcasecmp (header->name, hdr->name) != 0)
+                               continue;
+                       
+                       g_mime_event_remove (hdr->changed, (GMimeEventCallback) header_changed, headers);
+                       g_ptr_array_remove_index (headers->array, i);
+                       g_object_unref (hdr);
+               }
+               
+               args.action = GMIME_HEADER_LIST_CHANGED_ACTION_CHANGED;
+               args.header = header;
+               
+               g_mime_event_emit (headers->changed, &args);
+       } else {
+               _g_mime_header_list_append (headers, name, name, raw_value, -1);
+       }
+}
+
+
 /**
  * g_mime_header_list_set:
  * @headers: a #GMimeHeaderList
diff --git a/gmime/gmime-header.h b/gmime/gmime-header.h
index 4e56008..8a6b853 100644
--- a/gmime/gmime-header.h
+++ b/gmime/gmime-header.h
@@ -109,6 +109,7 @@ const char *g_mime_header_get_value (GMimeHeader *header);
 void g_mime_header_set_value (GMimeHeader *header, GMimeFormatOptions *options, const char *value, const 
char *charset);
 
 const char *g_mime_header_get_raw_value (GMimeHeader *header);
+void g_mime_header_set_raw_value (GMimeHeader *header, const char *raw_value);
 
 gint64 g_mime_header_get_offset (GMimeHeader *header);
 
diff --git a/gmime/gmime-internal.h b/gmime/gmime-internal.h
index ab2373a..b1ad5d6 100644
--- a/gmime/gmime-internal.h
+++ b/gmime/gmime-internal.h
@@ -61,6 +61,7 @@ G_GNUC_INTERNAL GMimeParserOptions *_g_mime_header_list_get_options (GMimeHeader
 G_GNUC_INTERNAL void _g_mime_header_list_set_options (GMimeHeaderList *headers, GMimeParserOptions *options);
 G_GNUC_INTERNAL void _g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char 
*raw_name,
                                                 const char *raw_value, gint64 offset);
+G_GNUC_INTERNAL void _g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char 
*raw_value);
 
 /* GMimeObject */
 G_GNUC_INTERNAL void _g_mime_object_block_header_list_changed (GMimeObject *object);
diff --git a/gmime/gmime-message.c b/gmime/gmime-message.c
index 277d449..2aa8618 100644
--- a/gmime/gmime-message.c
+++ b/gmime/gmime-message.c
@@ -730,17 +730,22 @@ g_mime_message_get_bcc (GMimeMessage *message)
 static void
 sync_internet_address_list (InternetAddressList *list, GMimeMessage *message, const char *name)
 {
-       GMimeFormatOptions *options = g_mime_format_options_get_default ();
        GMimeObject *object = (GMimeObject *) message;
-       char *string;
+       GString *str;
+       guint n;
        
-       string = internet_address_list_to_string (list, options, TRUE);
+       str = g_string_new (name);
+       g_string_append_c (str, ':');
+       n = str->len;
+       
+       g_string_append_c (str, ' ');
+       internet_address_list_encode (list, NULL, str);
        
        _g_mime_object_block_header_list_changed (object);
-       g_mime_object_set_header (object, name, string, NULL);
+       _g_mime_header_list_set (object->headers, name, str->str + n);
        _g_mime_object_unblock_header_list_changed (object);
        
-       g_free (string);
+       g_string_free (str, TRUE);
 }
 
 static void
diff --git a/gmime/gmime-object.c b/gmime/gmime-object.c
index cff90d4..f59042d 100644
--- a/gmime/gmime-object.c
+++ b/gmime/gmime-object.c
@@ -315,77 +315,30 @@ _g_mime_object_unblock_header_list_changed (GMimeObject *object)
        g_mime_event_unblock (object->headers->changed, (GMimeEventCallback) header_list_changed, object);
 }
 
-static char *
-unfold_raw_value (const char *raw_value)
-{
-       char *value = g_malloc (strlen (raw_value) + 1);
-       register const char *inptr = raw_value;
-       register char *outptr = value;
-       
-       while (is_lwsp (*inptr))
-               inptr++;
-       
-       while (*inptr) {
-               if (*inptr == '\n') {
-                       inptr++;
-                       
-                       if (*inptr == '\0')
-                               break;
-                       
-                       if (*inptr == '\t') {
-                               *outptr++ = ' ';
-                               inptr++;
-                       } else {
-                               *outptr++ = *inptr++;
-                       }
-               } else {
-                       *outptr++ = *inptr++;
-               }
-       }
-       
-       *outptr = '\0';
-       
-       return value;
-}
-
 static void
 content_type_changed (GMimeContentType *content_type, gpointer args, GMimeObject *object)
 {
-       GMimeFormatOptions *options = g_mime_format_options_get_default ();
-       char *raw_value, *value;
-       GMimeHeader *header;
+       char *raw_value;
        
-       raw_value = g_mime_content_type_encode (content_type, options);
-       value = unfold_raw_value (raw_value);
+       raw_value = g_mime_content_type_encode (content_type, NULL);
        
        _g_mime_object_block_header_list_changed (object);
-       g_mime_header_list_set (object->headers, "Content-Type", value, NULL);
-       header = g_mime_header_list_get_header (object->headers, "Content-Type");
-       _g_mime_header_set_raw_value (header, raw_value);
+       _g_mime_header_list_set (object->headers, "Content-Type", raw_value);
        _g_mime_object_unblock_header_list_changed (object);
        g_free (raw_value);
-       g_free (value);
 }
 
 static void
 content_disposition_changed (GMimeContentDisposition *disposition, gpointer args, GMimeObject *object)
 {
-       GMimeFormatOptions *options;
-       char *raw_value, *value;
-       GMimeHeader *header;
+       char *raw_value;
        
        _g_mime_object_block_header_list_changed (object);
        
-       if (object->disposition) {
-               options = g_mime_format_options_get_default ();
-               raw_value = g_mime_content_disposition_encode (object->disposition, options);
-               value = unfold_raw_value (raw_value);
-               
-               g_mime_header_list_set (object->headers, "Content-Disposition", value, NULL);
-               header = g_mime_header_list_get_header (object->headers, "Content-Disposition");
-               _g_mime_header_set_raw_value (header, raw_value);
+       if (disposition) {
+               raw_value = g_mime_content_disposition_encode (disposition, NULL);
+               _g_mime_header_list_set (object->headers, "Content-Disposition", raw_value);
                g_free (raw_value);
-               g_free (value);
        } else {
                g_mime_header_list_remove (object->headers, "Content-Disposition");
        }
diff --git a/gmime/internet-address.c b/gmime/internet-address.c
index b23971c..5fb4838 100644
--- a/gmime/internet-address.c
+++ b/gmime/internet-address.c
@@ -1053,18 +1053,22 @@ encoded_name (GMimeFormatOptions *options, const char *raw, gboolean rfc2047_enc
 }
 
 static void
-linewrap (GString *string)
+linewrap (GString *str, const char *newline)
 {
-       if (string->len > 0 && string->str[string->len - 1] == ' ') {
-               string->str[string->len - 1] = '\n';
-               g_string_append_c (string, '\t');
+       if (str->len > 0 && str->str[str->len - 1] == ' ') {
+               str->str[str->len - 1] = newline[0];
+               
+               if (newline[1])
+                       g_string_append_c (str, newline[1]);
        } else {
-               g_string_append (string, "\n\t");
+               g_string_append (str, newline);
        }
+       
+       g_string_append_c (str, '\t');
 }
 
 static void
-append_folded_name (GString *string, size_t *linelen, const char *name)
+append_folded_name (GString *str, size_t *linelen, const char *name, const char *newline)
 {
        const char *word, *lwsp;
        size_t len;
@@ -1096,11 +1100,11 @@ append_folded_name (GString *string, size_t *linelen, const char *name)
                
                len = lwsp - word;
                if (*linelen > 1 && (*linelen + len) > GMIME_FOLD_LEN) {
-                       linewrap (string);
+                       linewrap (str, newline);
                        *linelen = 1;
                }
                
-               g_string_append_len (string, word, len);
+               g_string_append_len (str, word, len);
                *linelen += len;
                
                word = lwsp;
@@ -1108,21 +1112,24 @@ append_folded_name (GString *string, size_t *linelen, const char *name)
                        word++;
                
                if (*word && is_lwsp (*lwsp)) {
-                       g_string_append_c (string, ' ');
+                       g_string_append_c (str, ' ');
                        (*linelen)++;
                }
        }
 }
 
 static void
-mailbox_to_string (InternetAddress *ia, GMimeFormatOptions *options, guint32 flags, size_t *linelen, GString 
*string)
+mailbox_to_string (InternetAddress *ia, GMimeFormatOptions *options, guint32 flags, size_t *linelen, GString 
*str)
 {
        InternetAddressMailbox *mailbox = (InternetAddressMailbox *) ia;
        gboolean encode = flags & INTERNET_ADDRESS_ENCODE;
        gboolean fold = flags & INTERNET_ADDRESS_FOLD;
+       const char *newline;
        char *name;
        size_t len;
        
+       newline = g_mime_format_options_get_newline (options);
+       
        if (ia->name && *ia->name) {
                name = encoded_name (options, ia->name, encode, ia->charset);
                len = strlen (name);
@@ -1130,21 +1137,21 @@ mailbox_to_string (InternetAddress *ia, GMimeFormatOptions *options, guint32 fla
                if (fold && (*linelen + len) > GMIME_FOLD_LEN) {
                        if (len > GMIME_FOLD_LEN) {
                                /* we need to break up the name */
-                               append_folded_name (string, linelen, name);
+                               append_folded_name (str, linelen, name, newline);
                        } else {
                                /* the name itself is short enough to fit on a single
                                 * line, but only if we write it on a line by itself */
                                if (*linelen > 1) {
-                                       linewrap (string);
+                                       linewrap (str, newline);
                                        *linelen = 1;
                                }
                                
-                               g_string_append_len (string, name, len);
+                               g_string_append_len (str, name, len);
                                *linelen += len;
                        }
                } else {
                        /* we can safely fit the name on this line */
-                       g_string_append_len (string, name, len);
+                       g_string_append_len (str, name, len);
                        *linelen += len;
                }
                
@@ -1153,32 +1160,33 @@ mailbox_to_string (InternetAddress *ia, GMimeFormatOptions *options, guint32 fla
                len = strlen (mailbox->addr);
                
                if (fold && (*linelen + len + 3) >= GMIME_FOLD_LEN) {
-                       g_string_append_len (string, "\n\t<", 3);
+                       g_string_append (str, newline);
+                       g_string_append_len (str, "\t<", 2);
                        *linelen = 2;
                } else {
-                       g_string_append_len (string, " <", 2);
+                       g_string_append_len (str, " <", 2);
                        *linelen += 2;
                }
                
-               g_string_append_len (string, mailbox->addr, len);
-               g_string_append_c (string, '>');
+               g_string_append_len (str, mailbox->addr, len);
+               g_string_append_c (str, '>');
                *linelen += len + 1;
        } else {
                len = strlen (mailbox->addr);
                
                if (fold && (*linelen + len) > GMIME_FOLD_LEN) {
-                       linewrap (string);
+                       linewrap (str, newline);
                        *linelen = 1;
                }
                
-               g_string_append_len (string, mailbox->addr, len);
+               g_string_append_len (str, mailbox->addr, len);
                *linelen += len;
        }
 }
 
 static void
 _internet_address_list_to_string (const InternetAddressList *list, GMimeFormatOptions *options, guint32 
flags,
-                                 size_t *linelen, GString *string)
+                                 size_t *linelen, GString *str)
 {
        InternetAddress *ia;
        guint i;
@@ -1186,42 +1194,45 @@ _internet_address_list_to_string (const InternetAddressList *list, GMimeFormatOp
        for (i = 0; i < list->array->len; i++) {
                ia = (InternetAddress *) list->array->pdata[i];
                
-               INTERNET_ADDRESS_GET_CLASS (ia)->to_string (ia, options, flags, linelen, string);
+               INTERNET_ADDRESS_GET_CLASS (ia)->to_string (ia, options, flags, linelen, str);
                
                if (i + 1 < list->array->len) {
-                       g_string_append (string, ", ");
+                       g_string_append (str, ", ");
                        *linelen += 2;
                }
        }
 }
 
 static void
-group_to_string (InternetAddress *ia, GMimeFormatOptions *options, guint32 flags, size_t *linelen, GString 
*string)
+group_to_string (InternetAddress *ia, GMimeFormatOptions *options, guint32 flags, size_t *linelen, GString 
*str)
 {
        InternetAddressGroup *group = (InternetAddressGroup *) ia;
        gboolean encode = flags & INTERNET_ADDRESS_ENCODE;
        gboolean fold = flags & INTERNET_ADDRESS_FOLD;
+       const char *newline;
        char *name = NULL;
        size_t len = 0;
        
+       newline = g_mime_format_options_get_newline (options);
+       
        if (ia->name != NULL) {
                name = encoded_name (options, ia->name, encode, ia->charset);
                len = strlen (name);
                
                if (fold && *linelen > 1 && (*linelen + len + 1) > GMIME_FOLD_LEN) {
-                       linewrap (string);
+                       linewrap (str, newline);
                        *linelen = 1;
                }
                
-               g_string_append_len (string, name, len);
+               g_string_append_len (str, name, len);
        }
        
-       g_string_append_len (string, ": ", 2);
+       g_string_append_len (str, ": ", 2);
        *linelen += len + 2;
        g_free (name);
        
-       _internet_address_list_to_string (group->members, options, flags, linelen, string);
-       g_string_append_c (string, ';');
+       _internet_address_list_to_string (group->members, options, flags, linelen, str);
+       g_string_append_c (str, ';');
        *linelen += 1;
 }
 
@@ -1243,34 +1254,31 @@ internet_address_list_to_string (InternetAddressList *list, GMimeFormatOptions *
 {
        guint32 flags = encode ? INTERNET_ADDRESS_ENCODE : 0;
        size_t linelen = 0;
-       GString *string;
-       char *str;
+       GString *str;
        
        g_return_val_if_fail (IS_INTERNET_ADDRESS_LIST (list), NULL);
        
        if (list->array->len == 0)
                return NULL;
        
-       string = g_string_new ("");
-       _internet_address_list_to_string (list, options, flags, &linelen, string);
-       str = string->str;
-       
-       g_string_free (string, FALSE);
+       str = g_string_new ("");
+       _internet_address_list_to_string (list, options, flags, &linelen, str);
        
-       return str;
+       return g_string_free (str, FALSE);
 }
 
 
 /**
- * internet_address_list_writer:
+ * internet_address_list_encode:
  * @list: list of internet addresses
+ * @options: a #GMimeFormatOptions
  * @str: string to write to
  *
  * Writes the rfc2047-encoded rfc822 formatted addresses in @list to
  * @str, folding appropriately.
  **/
 void
-internet_address_list_writer (InternetAddressList *list, GMimeFormatOptions *options, GString *str)
+internet_address_list_encode (InternetAddressList *list, GMimeFormatOptions *options, GString *str)
 {
        guint32 flags = INTERNET_ADDRESS_ENCODE | INTERNET_ADDRESS_FOLD;
        size_t linelen = str->len;
diff --git a/gmime/internet-address.h b/gmime/internet-address.h
index dd4e89b..f2bebef 100644
--- a/gmime/internet-address.h
+++ b/gmime/internet-address.h
@@ -92,7 +92,7 @@ struct _InternetAddressClass {
        
        /* public virtual methods */
        void (* to_string) (InternetAddress *ia, GMimeFormatOptions *options, guint32 flags,
-                           size_t *linelen, GString *out);
+                           size_t *linelen, GString *str);
 };
 
 
@@ -207,11 +207,10 @@ InternetAddress *internet_address_list_get_address (InternetAddressList *list, i
 void internet_address_list_set_address (InternetAddressList *list, int index, InternetAddress *ia);
 
 char *internet_address_list_to_string (InternetAddressList *list, GMimeFormatOptions *options, gboolean 
encode);
+void internet_address_list_encode (InternetAddressList *list, GMimeFormatOptions *options, GString *str);
 
 InternetAddressList *internet_address_list_parse (GMimeParserOptions *options, const char *str);
 
-void internet_address_list_writer (InternetAddressList *list, GMimeFormatOptions *options, GString *str);
-
 G_END_DECLS
 
 #endif /* __INTERNET_ADDRESS_H__ */


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