Re: [gmime-devel] Mapping MIME parts to byte offsets



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]