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