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: Tue, 21 Apr 2009 10:55:31 -0400
Okay, so I actually started hacking on this last night by setting the
offsets on the GMimeHeaderList of each mime-part (I should probably set
it on the Message's HeaderList as well). After implementing the attached
patch, I am now thinking that I might like it to be on GMimeObject
instead, but I can't add it to GMimeObject w/o breaking ABI :-(
However... I noticed the other day while working on the Windows port
that in my effort to fix the off_t issue that I missed that
g_mime_stream_length() returns ssize_t which is not guaranteed to be
suitable for large file sizes. So it looks like I'll have to break
API/ABI again for a "2.6" anyway. I'll likely send out my ideas for a
2.6 to get feedback in another mail later this week (hopefully).
But back to the topic at hand...
I had a couple of questions about behavior:
- If you are ask for the message headers, presumably the begin/end
offsets should be for the entire header-block, correct? (vs some sort of
kludge to discount any MIME headers)
- But what if you ask for the toplevel mime-part's header offsets?
should they be identical to the offsets given when requesting for the
message? I presume this to be true, but I'm not sure.
The attached patch is what I've got hacked up so far if I have to
squeeze this feature into 2.4 (e.g. avoid breaking ABI). I'd have to
play around with adding the get_header_begin/end() APIs to GMimeObject
before I decide on which API I like best, and it also depends on whether
or not developers would expect these offsets to be updated as they
change the header values or not (god I hope not!), since if they did
expect that behavior, I think the offsets would have to live on the
GMimeHeaderList because it'd be too much of a pain otherwise (I'm pretty
sure projects like Bongo and DBMail do not care about the offsets being
updated since you guys would not be making such changes).
Okay, well I gotta run for now,
Jeff
Index: gmime/gmime-parser.c
===================================================================
--- gmime/gmime-parser.c (revision 1572)
+++ gmime/gmime-parser.c (working copy)
@@ -153,6 +153,10 @@
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;
@@ -363,6 +367,9 @@
priv->rawleft = HEADER_RAW_INIT_SIZE - 1;
priv->rawptr = priv->rawbuf;
+ priv->message_headers_begin = -1;
+ priv->message_headers_end = -1;
+
priv->headers_begin = -1;
priv->headers_end = -1;
@@ -955,11 +962,9 @@
raw_header_reset (priv);
header_raw_clear (&priv->headers);
tail = (HeaderRaw *) &priv->headers;
- priv->header_offset = parser_offset (priv, NULL);
+ priv->headers_begin = parser_offset (priv, NULL);
+ priv->header_offset = priv->headers_begin;
- if (priv->headers_begin == -1)
- priv->headers_begin = parser_offset (priv, NULL);
-
inptr = priv->inptr;
inend = priv->inend;
@@ -1089,9 +1094,7 @@
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';
priv->inptr = inptr;
@@ -1100,9 +1103,7 @@
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';
priv->inptr = start;
@@ -1111,9 +1112,7 @@
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';
priv->inptr = start;
@@ -1210,20 +1209,25 @@
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)
@@ -1520,6 +1524,8 @@
header_raw_clear (&priv->headers);
+ g_mime_header_list_set_headers_begin (object->headers, priv->headers_begin);
+ g_mime_header_list_set_headers_end (object->headers, priv->headers_end);
g_mime_header_list_set_raw (object->headers, priv->rawbuf);
raw_header_reset (priv);
@@ -1668,6 +1674,8 @@
header_raw_clear (&priv->headers);
+ g_mime_header_list_set_headers_begin (object->headers, priv->headers_begin);
+ g_mime_header_list_set_headers_end (object->headers, priv->headers_end);
g_mime_header_list_set_raw (object->headers, priv->rawbuf);
raw_header_reset (priv);
@@ -1896,7 +1904,7 @@
{
g_return_val_if_fail (GMIME_IS_PARSER (parser), -1);
- return parser->priv->headers_begin;
+ return parser->priv->message_headers_begin;
}
@@ -1915,5 +1923,5 @@
{
g_return_val_if_fail (GMIME_IS_PARSER (parser), -1);
- return parser->priv->headers_end;
+ return parser->priv->message_headers_end;
}
Index: gmime/gmime-header.c
===================================================================
--- gmime/gmime-header.c (revision 1572)
+++ gmime/gmime-header.c (working copy)
@@ -68,6 +68,8 @@
GHashTable *writers;
GHashTable *hash;
guint32 version;
+ gint64 begin;
+ gint64 end;
List list;
char *raw;
};
@@ -536,6 +538,8 @@
list_init (&headers->list);
headers->version = 0;
headers->raw = NULL;
+ headers->begin = -1;
+ headers->end = -1;
return headers;
}
@@ -571,6 +575,72 @@
/**
+ * g_mime_header_list_set_headers_begin:
+ * @headers: a #GMimeHeaderList
+ * @begin: begin offset
+ *
+ * Sets the stream offset of the beginning of the header list.
+ **/
+void
+g_mime_header_list_set_headers_begin (GMimeHeaderList *headers, gint64 begin)
+{
+ g_return_if_fail (headers != NULL);
+
+ headers->begin = begin;
+}
+
+
+/**
+ * g_mime_header_list_get_headers_begin:
+ * @headers: a #GMimeHeaderList
+ *
+ * Gets the stream offset of the beginning of the header list.
+ *
+ * Returns: the starting offset of the header list or %-1 if unknown.
+ **/
+gint64
+g_mime_header_list_get_headers_begin (const GMimeHeaderList *headers)
+{
+ g_return_val_if_fail (headers != NULL, -1);
+
+ return headers->begin;
+}
+
+
+/**
+ * g_mime_header_list_set_headers_end:
+ * @headers: a #GMimeHeaderList
+ * @begin: begin offset
+ *
+ * Sets the stream offset of the beginning of the header list.
+ **/
+void
+g_mime_header_list_set_headers_end (GMimeHeaderList *headers, gint64 end)
+{
+ g_return_if_fail (headers != NULL);
+
+ headers->end = end;
+}
+
+
+/**
+ * g_mime_header_list_get_headers_end:
+ * @headers: a #GMimeHeaderList
+ *
+ * Gets the stream offset of the end of the header list.
+ *
+ * Returns: the ending offset of the header list or %-1 if unknown.
+ **/
+gint64
+g_mime_header_list_get_bound_end (const GMimeHeaderList *headers)
+{
+ g_return_val_if_fail (headers != NULL, -1);
+
+ return headers->end;
+}
+
+
+/**
* g_mime_header_list_prepend:
* @headers: a #GMimeHeaderList
* @name: header name
Index: gmime/gmime-header.h
===================================================================
--- gmime/gmime-header.h (revision 1572)
+++ gmime/gmime-header.h (working copy)
@@ -108,6 +108,9 @@
void g_mime_header_list_destroy (GMimeHeaderList *headers);
+gint64 g_mime_header_list_get_headers_begin (const GMimeHeaderList *headers);
+gint64 g_mime_header_list_get_headers_end (const 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);
@@ -123,6 +126,8 @@
char *g_mime_header_list_to_string (const GMimeHeaderList *headers);
/* for internal use only */
+G_GNUC_INTERNAL void g_mime_header_list_set_headers_begin (GMimeHeaderList *headers, gint64 begin);
+G_GNUC_INTERNAL void g_mime_header_list_set_headers_end (GMimeHeaderList *headers, gint64 end);
void g_mime_header_list_set_raw (GMimeHeaderList *headers, const char *raw);
gboolean g_mime_header_list_has_raw (const GMimeHeaderList *headers);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]