Re: [gmime-devel] Mapping MIME parts to byte offsets
- From: Jeffrey Stedfast <fejj novell com>
- To: Alex Hudson <alex bongo-project org>
- Cc: gmime-devel-list gnome org
- Subject: Re: [gmime-devel] Mapping MIME parts to byte offsets
- Date: Fri, 24 Apr 2009 21:41:42 -0400
Okay, so I played around a bit more tonight and came up with the
attached patch that I like a lot and will likely be committing as-is.
The differences between this patch and the last patch are:
Instead of storing header offsets on the GMimeHeaderList, we now store a
substream of the input stream that was fed to the parser (which has the
offsets).
I like this API better because w/o the stream, the offsets are useless.
It should also make what you want to do extremely easy. It's also more
consistent with how I solve the same problem for GMimePart content.
And best of all... it means we don't have to dup the raw headers to
memory anymore. So it's a lot cleaner than what I had before to solve
the same problem, and is also a solution to the problem you had.
This is also safe to add to GMime 2.4 (no one should have been using the
g_mime_header_list_set/has_raw() APIs - altho to be safe, I should add
them back - this was a backport from what I'm working on on trunk).
Jeff
diff --git a/ChangeLog b/ChangeLog
index 9b51304..4680550 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,49 @@
+2009-04-24 Jeffrey Stedfast <fejj novell com>
+
+ * tests/test-parser.c (test_parser): Updated.
+
+ * gmime/gmime-parser.c (struct _GMimeParserPrivate): Added
+ message_headers_begin/end and changed the meaning of
+ headers_begin/end to be for the current MIME part rather than for
+ the current message itself.
+ (g_mime_parser_init): Init the boolean state variables before
+ calling parser_init() so that parser_init() can use them.
+ (parser_init): Only create a rawbuf if our stream isn't seekable
+ or isn't persistent. Initialize our new message_headers_begin/end.
+ (g_mime_parser_set_persist_stream): If our persist mode has
+ changed, malloc or free our rawbuf.
+ (raw_header_append): Don't append any data if rawbuf is NULL (this
+ means we're keeping track of offsets instead).
+ (parser_step_headers): Always update headers_begin/end since we
+ now always want to keep track of all header begin/end offsets.
+ (parser_step): Update our message_headers_begin/end state.
+ (parser_scan_message_part): Set the mime-part's raw header stream
+ on the message too.
+ (parser_construct_message): Same.
+ (parser_construct_leaf_part): Substream the input stream to get
+ our raw header stream to set on the mime-part's header-list.
+ (parser_construct_multipart): Same.
+
+ * gmime/gmime-header.c (struct _GMimeHeaderList): Instead of
+ having a string buffer holding the raw header block content,
+ instead keep a stream. This not only makes it easy for us to keep
+ track of what the header offsets on disk are should the developer
+ want to know, but it also means we don't necessarily have to use
+ duplicate the header block to memory.
+ (g_mime_header_list_set_stream): New function that replaces the
+ old g_mime_header_list_set_raw() and looks much cleaner.
+ (g_mime_header_list_get_stream): New function to access said
+ stream.
+
+ * gmime/gmime-message.c: Fixed uses of
+ g_mime_header_list_set/has_raw().
+ (g_mime_message_set_mime_part): Set the message's raw header
+ stream to NULL.
+
+ * gmime/gmime-multipart.c: Same.
+
+ * tests/test-parser.c (test_parser): Updated.
+
2009-04-09 Jeffrey Stedfast <fejj novell com>
* README: Bumped version
diff --git a/gmime/gmime-header.c b/gmime/gmime-header.c
index e518688..23e5014 100644
--- a/gmime/gmime-header.c
+++ b/gmime/gmime-header.c
@@ -65,11 +65,11 @@ struct _GMimeHeader {
};
struct _GMimeHeaderList {
+ GMimeStream *stream;
GHashTable *writers;
GHashTable *hash;
guint32 version;
List list;
- char *raw;
};
@@ -429,7 +429,7 @@ 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_raw (iter->hdrlist, NULL);
+ g_mime_header_list_set_stream (iter->hdrlist, NULL);
return TRUE;
}
@@ -534,8 +534,8 @@ g_mime_header_list_new (void)
headers->hash = g_hash_table_new (g_mime_strcase_hash,
g_mime_strcase_equal);
list_init (&headers->list);
+ headers->stream = NULL;
headers->version = 0;
- headers->raw = NULL;
return headers;
}
@@ -564,7 +564,9 @@ g_mime_header_list_destroy (GMimeHeaderList *headers)
g_hash_table_destroy (headers->writers);
g_hash_table_destroy (headers->hash);
- g_free (headers->raw);
+
+ if (headers->stream)
+ g_object_unref (headers->stream);
g_slice_free (GMimeHeaderList, headers);
}
@@ -592,8 +594,10 @@ g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const ch
list_append (&headers->list, (ListNode *) header);
g_hash_table_replace (headers->hash, header->name, header);
- g_free (headers->raw);
- headers->raw = NULL;
+ if (headers->stream) {
+ g_object_unref (headers->stream);
+ headers->stream = NULL;
+ }
}
@@ -621,8 +625,10 @@ g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const cha
if (!g_hash_table_lookup (headers->hash, name))
g_hash_table_insert (headers->hash, header->name, header);
- g_free (headers->raw);
- headers->raw = NULL;
+ if (headers->stream) {
+ g_object_unref (headers->stream);
+ headers->stream = NULL;
+ }
}
@@ -696,8 +702,10 @@ g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *
g_hash_table_insert (headers->hash, header->name, header);
}
- g_free (headers->raw);
- headers->raw = NULL;
+ if (headers->stream) {
+ g_object_unref (headers->stream);
+ headers->stream = NULL;
+ }
}
@@ -741,8 +749,10 @@ g_mime_header_list_remove (GMimeHeaderList *headers, const char *name)
list_unlink ((ListNode *) header);
g_mime_header_free (header);
- g_free (headers->raw);
- headers->raw = NULL;
+ if (headers->stream) {
+ g_object_unref (headers->stream);
+ headers->stream = NULL;
+ }
return TRUE;
}
@@ -836,8 +846,10 @@ g_mime_header_list_write_to_stream (const GMimeHeaderList *headers, GMimeStream
g_return_val_if_fail (headers != NULL, -1);
g_return_val_if_fail (stream != NULL, -1);
- if (headers->raw)
- return g_mime_stream_write_string (stream, headers->raw);
+ 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;
@@ -878,13 +890,17 @@ g_mime_header_list_to_string (const GMimeHeaderList *headers)
g_return_val_if_fail (headers != NULL, NULL);
- if (headers->raw)
- return g_strdup (headers->raw);
-
array = g_byte_array_new ();
stream = g_mime_stream_mem_new ();
g_mime_stream_mem_set_byte_array (GMIME_STREAM_MEM (stream), array);
- g_mime_header_list_write_to_stream (headers, stream);
+
+ 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_object_unref (stream);
g_byte_array_append (array, (unsigned char *) "", 1);
@@ -926,34 +942,40 @@ g_mime_header_list_register_writer (GMimeHeaderList *headers, const char *name,
/**
- * g_mime_header_list_set_raw:
+ * g_mime_header_list_set_stream:
* @headers: a #GMimeHeaderList
- * @raw: raw mime part header
+ * @stream: a #GMimeStream
*
- * Set the raw header.
+ * Set the raw header stream.
**/
void
-g_mime_header_list_set_raw (GMimeHeaderList *headers, const char *raw)
+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);
- g_free (headers->raw);
- headers->raw = raw ? g_strdup (raw) : NULL;
+ if (stream)
+ g_object_ref (stream);
+
+ if (headers->stream)
+ g_object_unref (headers->stream);
+
+ headers->stream = stream;
}
/**
- * g_mime_header_list_has_raw:
+ * g_mime_header_list_get_stream:
* @headers: a #GMimeHeaderList
*
- * Gets whether or not a raw header has been set on @headers.
+ * Gets the raw stream representing @headers.
*
- * Returns: %TRUE if a raw header is set or %FALSE otherwise.
+ * Returns: a #GMimeStream if set or %NULL otherwise.
**/
-gboolean
-g_mime_header_list_has_raw (const GMimeHeaderList *headers)
+GMimeStream *
+g_mime_header_list_get_stream (GMimeHeaderList *headers)
{
- g_return_val_if_fail (headers != NULL, FALSE);
+ g_return_val_if_fail (headers != NULL, NULL);
- return headers->raw ? TRUE : FALSE;
+ return headers->stream;
}
diff --git a/gmime/gmime-header.h b/gmime/gmime-header.h
index ac4b972..1b8fad7 100644
--- a/gmime/gmime-header.h
+++ b/gmime/gmime-header.h
@@ -87,6 +87,7 @@ gboolean g_mime_header_iter_prev (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);
+
gboolean g_mime_header_iter_remove (GMimeHeaderIter *iter);
@@ -108,6 +109,9 @@ GMimeHeaderList *g_mime_header_list_new (void);
void g_mime_header_list_destroy (GMimeHeaderList *headers);
+void g_mime_header_list_set_stream (GMimeHeaderList *headers, GMimeStream *stream);
+GMimeStream *g_mime_header_list_get_stream (GMimeHeaderList *headers);
+
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);
@@ -122,10 +126,6 @@ void g_mime_header_list_register_writer (GMimeHeaderList *headers, const char *n
ssize_t g_mime_header_list_write_to_stream (const GMimeHeaderList *headers, GMimeStream *stream);
char *g_mime_header_list_to_string (const GMimeHeaderList *headers);
-/* for internal use only */
-void g_mime_header_list_set_raw (GMimeHeaderList *headers, const char *raw);
-gboolean g_mime_header_list_has_raw (const GMimeHeaderList *headers);
-
G_END_DECLS
#endif /* __GMIME_HEADER_H__ */
diff --git a/gmime/gmime-message.c b/gmime/gmime-message.c
index 3e450dd..cf4ade5 100644
--- a/gmime/gmime-message.c
+++ b/gmime/gmime-message.c
@@ -48,10 +48,10 @@
typedef void (* EventCallback) (gpointer sender, gpointer args);
-void _internet_address_list_block_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data);
-void _internet_address_list_unblock_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data);
-void _internet_address_list_add_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data);
-void _internet_address_list_remove_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data);
+extern void _internet_address_list_block_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data);
+extern void _internet_address_list_unblock_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data);
+extern void _internet_address_list_add_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data);
+extern void _internet_address_list_remove_event_handler (InternetAddressList *list, EventCallback callback, gpointer user_data);
static void g_mime_message_class_init (GMimeMessageClass *klass);
@@ -790,7 +790,7 @@ message_prepend_header (GMimeObject *object, const char *header, const char *val
g_mime_header_list_prepend (object->headers, header, value);
if (message->mime_part)
- g_mime_header_list_set_raw (message->mime_part->headers, NULL);
+ g_mime_header_list_set_stream (message->mime_part->headers, NULL);
}
static void
@@ -812,7 +812,7 @@ message_append_header (GMimeObject *object, const char *header, const char *valu
g_mime_header_list_append (object->headers, header, value);
if (message->mime_part)
- g_mime_header_list_set_raw (message->mime_part->headers, NULL);
+ g_mime_header_list_set_stream (message->mime_part->headers, NULL);
}
static void
@@ -834,7 +834,7 @@ message_set_header (GMimeObject *object, const char *header, const char *value)
g_mime_header_list_set (object->headers, header, value);
if (message->mime_part)
- g_mime_header_list_set_raw (message->mime_part->headers, NULL);
+ g_mime_header_list_set_stream (message->mime_part->headers, NULL);
}
static const char *
@@ -927,7 +927,7 @@ message_remove_header (GMimeObject *object, const char *header)
}
if (message->mime_part)
- g_mime_header_list_set_raw (message->mime_part->headers, NULL);
+ g_mime_header_list_set_stream (message->mime_part->headers, NULL);
return GMIME_OBJECT_CLASS (parent_class)->remove_header (object, header);
}
@@ -945,7 +945,7 @@ message_get_headers (GMimeObject *object)
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_has_raw (message->mime_part->headers)) {
+ 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 {
@@ -972,9 +972,9 @@ message_write_to_stream (GMimeObject *object, GMimeStream *stream)
ssize_t nwritten, total = 0;
if (message->mime_part) {
- if (!g_mime_header_list_has_raw (message->mime_part->headers)) {
- /* if the mime part has raw headers, then it contains the message
- * headers as well otherwise it doesn't, so write them now */
+ if (!g_mime_header_list_get_stream (message->mime_part->headers)) {
+ /* if the mime part has a raw header stream, then it contains the
+ * message headers as well otherwise it doesn't, so write them now */
if ((nwritten = g_mime_header_list_write_to_stream (object->headers, stream)) == -1)
return -1;
@@ -1444,13 +1444,15 @@ g_mime_message_set_mime_part (GMimeMessage *message, GMimeObject *mime_part)
g_return_if_fail (GMIME_IS_OBJECT (mime_part));
g_object_ref (mime_part);
- g_mime_header_list_set_raw (mime_part->headers, NULL);
+ g_mime_header_list_set_stream (mime_part->headers, NULL);
if (message->mime_part) {
- g_mime_header_list_set_raw (message->mime_part->headers, NULL);
+ g_mime_header_list_set_stream (message->mime_part->headers, NULL);
g_object_unref (message->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 32ef7b0..a5d26d8 100644
--- a/gmime/gmime-multipart.c
+++ b/gmime/gmime-multipart.c
@@ -244,7 +244,7 @@ multipart_write_to_stream (GMimeObject *object, GMimeStream *stream)
* 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_has_raw (object->headers)) {
+ 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");
}
diff --git a/gmime/gmime-parser.c b/gmime/gmime-parser.c
index cb58a98..f196ca1 100644
--- a/gmime/gmime-parser.c
+++ b/gmime/gmime-parser.c
@@ -153,6 +153,10 @@ struct _GMimeParserPrivate {
size_t rawleft;
/* current message headerblock offsets */
+ gint64 message_headers_begin;
+ gint64 message_headers_end;
+
+ /* current mime-part headerblock offsets */
gint64 headers_begin;
gint64 headers_end;
@@ -298,16 +302,16 @@ static void
g_mime_parser_init (GMimeParser *parser, GMimeParserClass *klass)
{
parser->priv = g_new (struct _GMimeParserPrivate, 1);
- parser_init (parser, NULL);
+ parser->priv->respect_content_length = FALSE;
+ parser->priv->persist_stream = TRUE;
+ parser->priv->have_regex = FALSE;
+ parser->priv->scan_from = FALSE;
#if defined (HAVE_GLIB_REGEX)
parser->priv->regex = NULL;
#endif
- parser->priv->scan_from = FALSE;
- parser->priv->have_regex = FALSE;
- parser->priv->persist_stream = TRUE;
- parser->priv->respect_content_length = FALSE;
+ parser_init (parser, NULL);
}
static void
@@ -359,9 +363,18 @@ parser_init (GMimeParser *parser, GMimeStream *stream)
priv->headerleft = HEADER_INIT_SIZE - 1;
priv->headerptr = priv->headerbuf;
- priv->rawbuf = g_malloc (HEADER_RAW_INIT_SIZE);
- priv->rawleft = HEADER_RAW_INIT_SIZE - 1;
- priv->rawptr = priv->rawbuf;
+ 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->message_headers_begin = -1;
+ priv->message_headers_end = -1;
priv->headers_begin = -1;
priv->headers_end = -1;
@@ -501,9 +514,33 @@ 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));
- parser->priv->persist_stream = persist;
+ 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;
+ }
+ }
}
@@ -849,25 +886,29 @@ next_alloc_size (size_t n)
} G_STMT_END
#define raw_header_append(priv, start, len) G_STMT_START { \
- if (priv->rawleft <= len) { \
- size_t hlen, hoff; \
+ 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; \
+ } \
\
- 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; \
} \
- \
- memcpy (priv->rawptr, start, len); \
- priv->rawptr += len; \
- priv->rawleft -= len; \
} G_STMT_END
#define raw_header_reset(priv) G_STMT_START { \
- priv->rawleft += priv->rawptr - priv->rawbuf; \
- priv->rawptr = priv->rawbuf; \
+ if (priv->rawbuf) { \
+ priv->rawleft += priv->rawptr - priv->rawbuf; \
+ priv->rawptr = priv->rawbuf; \
+ } \
} G_STMT_END
static void
@@ -955,10 +996,8 @@ parser_step_headers (GMimeParser *parser)
raw_header_reset (priv);
header_raw_clear (&priv->headers);
tail = (HeaderRaw *) &priv->headers;
- priv->header_offset = parser_offset (priv, NULL);
-
- if (priv->headers_begin == -1)
- priv->headers_begin = parser_offset (priv, NULL);
+ priv->headers_begin = parser_offset (priv, NULL);
+ priv->header_offset = priv->headers_begin;
inptr = priv->inptr;
inend = priv->inend;
@@ -1089,33 +1128,30 @@ parser_step_headers (GMimeParser *parser)
if (priv->headerptr > priv->headerbuf)
header_parse (parser, &tail);
- if (priv->headers_end == -1)
- priv->headers_end = parser_offset (priv, start);
-
+ priv->headers_end = parser_offset (priv, start);
priv->state = GMIME_PARSER_STATE_HEADERS_END;
- *priv->rawptr = '\0';
+ if (priv->rawbuf)
+ *priv->rawptr = '\0';
priv->inptr = inptr;
return 0;
next_message:
- if (priv->headers_end == -1)
- priv->headers_end = parser_offset (priv, start);
-
+ priv->headers_end = parser_offset (priv, start);
priv->state = GMIME_PARSER_STATE_COMPLETE;
- *priv->rawptr = '\0';
+ if (priv->rawbuf)
+ *priv->rawptr = '\0';
priv->inptr = start;
return 0;
content_start:
- if (priv->headers_end == -1)
- priv->headers_end = parser_offset (priv, start);
-
+ priv->headers_end = parser_offset (priv, start);
priv->state = GMIME_PARSER_STATE_CONTENT;
- *priv->rawptr = '\0';
+ if (priv->rawbuf)
+ *priv->rawptr = '\0';
priv->inptr = start;
return 0;
@@ -1210,20 +1246,25 @@ parser_step (GMimeParser *parser)
case GMIME_PARSER_STATE_ERROR:
break;
case GMIME_PARSER_STATE_INIT:
- parser->priv->headers_begin = -1;
- parser->priv->headers_end = -1;
+ priv->message_headers_begin = -1;
+ priv->message_headers_end = -1;
if (priv->scan_from)
priv->state = GMIME_PARSER_STATE_FROM;
else
priv->state = GMIME_PARSER_STATE_HEADERS;
break;
case GMIME_PARSER_STATE_FROM:
- parser->priv->headers_begin = -1;
- parser->priv->headers_end = -1;
+ priv->message_headers_begin = -1;
+ priv->message_headers_end = -1;
parser_step_from (parser);
break;
case GMIME_PARSER_STATE_HEADERS:
parser_step_headers (parser);
+
+ if (priv->message_headers_begin == -1) {
+ priv->message_headers_begin = priv->headers_begin;
+ priv->message_headers_end = priv->headers_end;
+ }
break;
case GMIME_PARSER_STATE_HEADERS_END:
if (parser_skip_line (parser) == -1)
@@ -1460,6 +1501,7 @@ parser_scan_message_part (GMimeParser *parser, GMimeMessagePart *mpart, int *fou
ContentType *content_type;
GMimeMessage *message;
GMimeObject *object;
+ GMimeStream *stream;
HeaderRaw *header;
g_assert (priv->state == GMIME_PARSER_STATE_CONTENT);
@@ -1489,6 +1531,10 @@ 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);
}
@@ -1498,6 +1544,7 @@ parser_construct_leaf_part (GMimeParser *parser, ContentType *content_type, int
{
struct _GMimeParserPrivate *priv = parser->priv;
GMimeObject *object;
+ GMimeStream *stream;
HeaderRaw *header;
g_assert (priv->state >= GMIME_PARSER_STATE_HEADERS_END);
@@ -1520,7 +1567,15 @@ parser_construct_leaf_part (GMimeParser *parser, ContentType *content_type, int
header_raw_clear (&priv->headers);
- g_mime_header_list_set_raw (object->headers, priv->rawbuf);
+ /* 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) {
@@ -1654,6 +1709,7 @@ parser_construct_multipart (GMimeParser *parser, ContentType *content_type, int
GMimeMultipart *multipart;
const char *boundary;
GMimeObject *object;
+ GMimeStream *stream;
HeaderRaw *header;
g_assert (priv->state >= GMIME_PARSER_STATE_HEADERS_END);
@@ -1668,7 +1724,15 @@ parser_construct_multipart (GMimeParser *parser, ContentType *content_type, int
header_raw_clear (&priv->headers);
- g_mime_header_list_set_raw (object->headers, priv->rawbuf);
+ /* 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;
@@ -1758,6 +1822,7 @@ parser_construct_message (GMimeParser *parser)
ContentType *content_type;
GMimeMessage *message;
GMimeObject *object;
+ GMimeStream *stream;
HeaderRaw *header;
char *endptr;
int found;
@@ -1802,6 +1867,10 @@ 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);
@@ -1896,7 +1965,7 @@ g_mime_parser_get_headers_begin (GMimeParser *parser)
{
g_return_val_if_fail (GMIME_IS_PARSER (parser), -1);
- return parser->priv->headers_begin;
+ return parser->priv->message_headers_begin;
}
@@ -1915,5 +1984,5 @@ g_mime_parser_get_headers_end (GMimeParser *parser)
{
g_return_val_if_fail (GMIME_IS_PARSER (parser), -1);
- return parser->priv->headers_end;
+ return parser->priv->message_headers_end;
}
diff --git a/tests/test-parser.c b/tests/test-parser.c
index 213a771..f2562ff 100644
--- a/tests/test-parser.c
+++ b/tests/test-parser.c
@@ -129,11 +129,11 @@ test_parser (GMimeStream *stream)
{
GMimeStream *stream;
- g_mime_header_list_set_raw (GMIME_OBJECT (message)->headers, NULL);
+ 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_raw (GMIME_OBJECT (message)->headers, NULL);*/
+ /*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]