PATCH: GMime support for message reading



Hi,

Here is a first version of the GMime support. This patch changes the msg
loading/decoding over to GMime. I have done some basic tests on some mbox
mailfolders, other types are not tested. But i think there isn't much
changed there. The sending and printing parts are not yet changed over,
and there is some more cleanup possible.
The patch has some changes in libbalsa/send.c, they are mostly cleanup 
except for
-       } else {
-           /* safe_free bug patch: steal it! */
-           msg->content = mutt_copy_body(body->mutt_body, NULL);
which is called on process queue, but it looks like it's not necessary.


I like to hear what you think about this patch.

Bart
BTW This msg is send with this patch applied.
--
GPG key = 1024D/4B086D06 Fingerprint = CD4D 5601 287D F075 6F96  6157 99F9
E56A 4B08 6D06
Index: libbalsa/body.c
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/body.c,v
retrieving revision 1.14
diff -u -b -B -w -p -r1.14 body.c
--- libbalsa/body.c	2001/09/22 16:44:16	1.14
+++ libbalsa/body.c	2001/10/16 22:54:30
@@ -46,6 +46,8 @@ libbalsa_message_body_new(LibBalsaMessag
     body->next = NULL;
     body->parts = NULL;
 
+    body->mime_part = NULL;
+
     return body;
 }
 
@@ -75,49 +77,50 @@ libbalsa_message_body_free(LibBalsaMessa
 }
 
 void
-libbalsa_message_body_set_mutt_body(LibBalsaMessageBody * body,
-				    MuttBody * mutt_body)
+libbalsa_message_body_set_mime_body(LibBalsaMessageBody * body,
+				    GMimePart * mime_part)
 {
-    g_return_if_fail(body->mutt_body == NULL);
+    g_return_if_fail(body->mime_part == NULL);
 
-    body->mutt_body = mutt_body;
-    body->filename = g_strdup(mutt_body->filename);
-    if(body->filename)
-	rfc2047_decode(&body->filename);
-    if (mutt_body->next) {
-	body->next = libbalsa_message_body_new(body->message);
-	libbalsa_message_body_set_mutt_body(body->next, mutt_body->next);
-    }
-
-    if (mutt_body->parts) {
-	body->parts = libbalsa_message_body_new(body->message);
-	libbalsa_message_body_set_mutt_body(body->parts, mutt_body->parts);
+    body->mime_part = mime_part;
+    if (mime_part->children) {
+	LibBalsaMessageBody *part=NULL;
+	GList *child;
+	for (child=mime_part->children; child; child=g_list_next(child))
+	{
+	    if (!part) {
+		part=body->parts = libbalsa_message_body_new(body->message);
+	    } else {
+		part->next = libbalsa_message_body_new(body->message);
+		part=part->next;
     }
+	    libbalsa_message_body_set_mime_body(part, child->data);
 }
+    }
+}
 
 LibBalsaMessageBodyType
 libbalsa_message_body_type(LibBalsaMessageBody * body)
 {
-    switch (body->mutt_body->type) {
-    case TYPEOTHER:
-	return LIBBALSA_MESSAGE_BODY_TYPE_OTHER;
-    case TYPEAUDIO:
+    const GMimeContentType *type=g_mime_part_get_content_type(body->mime_part);
+
+    if      (g_mime_content_type_is_type(type, "audio", "*"))
 	return LIBBALSA_MESSAGE_BODY_TYPE_AUDIO;
-    case TYPEAPPLICATION:
+    else if (g_mime_content_type_is_type(type, "application", "*"))
 	return LIBBALSA_MESSAGE_BODY_TYPE_APPLICATION;
-    case TYPEIMAGE:
+    else if (g_mime_content_type_is_type(type, "image", "*"))
 	return LIBBALSA_MESSAGE_BODY_TYPE_IMAGE;
-    case TYPEMESSAGE:
+    else if (g_mime_content_type_is_type(type, "message", "*"))
 	return LIBBALSA_MESSAGE_BODY_TYPE_MESSAGE;
-    case TYPEMODEL:
+    else if (g_mime_content_type_is_type(type, "model", "*"))
 	return LIBBALSA_MESSAGE_BODY_TYPE_MODEL;
-    case TYPEMULTIPART:
+    else if (g_mime_content_type_is_type(type, "multipart", "*"))
 	return LIBBALSA_MESSAGE_BODY_TYPE_MULTIPART;
-    case TYPETEXT:
+    else if (g_mime_content_type_is_type(type, "text", "*"))
 	return LIBBALSA_MESSAGE_BODY_TYPE_TEXT;
-    case TYPEVIDEO:
+    else if (g_mime_content_type_is_type(type, "video", "*"))
 	return LIBBALSA_MESSAGE_BODY_TYPE_VIDEO;
-    }
+    else return LIBBALSA_MESSAGE_BODY_TYPE_OTHER;
 
     g_assert_not_reached();
     return LIBBALSA_MESSAGE_BODY_TYPE_OTHER;
@@ -127,13 +130,13 @@ gchar *
 libbalsa_message_body_get_parameter(LibBalsaMessageBody * body,
 				    const gchar * param)
 {
-    gchar *res;
+    const gchar *res;
+    const GMimeContentType *type;
 
     g_return_val_if_fail(body != NULL, NULL);
 
-    libbalsa_lock_mutt();
-    res = mutt_get_parameter(param, body->mutt_body->parameter);
-    libbalsa_unlock_mutt();
+    type=g_mime_part_get_content_type(body->mime_part);
+    res = g_mime_content_type_get_parameter(type, param);
 
     return g_strdup(res);
 }
@@ -178,32 +181,17 @@ gboolean
 libbalsa_message_body_save(LibBalsaMessageBody * body, gchar * prefix,
 			   gchar * filename)
 {
-    FILE *stream;
-    STATE s;
-
-    stream =
-	libbalsa_mailbox_get_message_stream(body->message->mailbox,
-					    body->message);
-
-    g_return_val_if_fail(stream != NULL, FALSE);
-
-    fseek(stream, body->mutt_body->offset, 0);
-
-    s.fpin = stream;
-
-    s.prefix = prefix;
-    s.fpout = safe_fopen(filename, "w");
-    if (!s.fpout)
+    FILE *fpout;
+    const gchar *buf;
+    guint len;
+    fpout=safe_fopen(filename, "w");
+    if (!fpout)
 	return FALSE;
+    buf=g_mime_part_get_content(body->mime_part, &len);
+    fwrite(buf, len , 1, fpout);
+    fflush(fpout);
+    fclose(fpout);
 
-    libbalsa_lock_mutt();
-    mutt_decode_attachment(body->mutt_body, &s);
-    libbalsa_unlock_mutt();
-
-    fflush(s.fpout);
-    fclose(s.fpout);
-    fclose(s.fpin);
-
     return TRUE;
 }
 
@@ -211,19 +199,15 @@ gchar *
 libbalsa_message_body_get_content_type(LibBalsaMessageBody * body)
 {
     gchar *res;
-
-    if (body->mutt_body->subtype)
-	res =
-	    g_strdup_printf("%s/%s", TYPE(body->mutt_body),
-			    body->mutt_body->subtype);
-    else
-	res = g_strdup(TYPE(body->mutt_body));
 
+    const GMimeContentType *type=g_mime_part_get_content_type(body->mime_part);
+    res=g_mime_content_type_to_string(type);
+    g_strdown(res);
     return res;
 }
 
 gboolean
 libbalsa_message_body_is_multipart(LibBalsaMessageBody * body)
 {
-    return is_multipart(body->mutt_body);
+    return body->mime_part->children;
 }
Index: libbalsa/body.h
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/body.h,v
retrieving revision 1.10
diff -u -b -B -w -p -r1.10 body.h
--- libbalsa/body.h	2001/10/15 07:06:27	1.10
+++ libbalsa/body.h	2001/10/16 22:54:30
@@ -26,6 +26,7 @@
 #include <stdio.h>
 
 #include <glib.h>
+#include <gmime/gmime.h>
 
 typedef enum _LibBalsaMessageBodyType LibBalsaMessageBodyType;
 
@@ -50,6 +51,7 @@ struct _LibBalsaMessageBody {
     gboolean attach_as_extbody; /* if an attachment shall be appended as external-body (sending) */
     gchar *temp_filename;	/* Holds the filename of a the temporary file where this part is saved */
     gchar *charset;		/* the charset, used for sending, replying. */
+    GMimePart *mime_part;	/* mime body */
 
     LibBalsaMessageBody *next;	/* Next part in the message */
     LibBalsaMessageBody *parts;	/* The parts of a multipart or message/rfc822 message */
@@ -61,8 +63,8 @@ void libbalsa_message_body_free(LibBalsa
 LibBalsaMessageBodyType libbalsa_message_body_type(LibBalsaMessageBody *
 						   body);
 
-void libbalsa_message_body_set_mutt_body(LibBalsaMessageBody * body,
-					 MuttBody * mutt_body);
+void libbalsa_message_body_set_mime_body(LibBalsaMessageBody * body,
+					 GMimePart * mime_part);
 
 gboolean libbalsa_message_body_save(LibBalsaMessageBody * body,
 				    gchar * prefixm, gchar * filename);
Index: libbalsa/message.c
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/message.c,v
retrieving revision 1.65
diff -u -b -B -w -p -r1.65 message.c
--- libbalsa/message.c	2001/10/08 22:16:16	1.65
+++ libbalsa/message.c	2001/10/16 22:54:35
@@ -47,6 +47,8 @@
 #include "threads.h"
 #endif
 
+#include <gmime/gmime.h>
+
 static void libbalsa_message_class_init(LibBalsaMessageClass * klass);
 static void libbalsa_message_init(LibBalsaMessage * message);
 
@@ -294,27 +296,22 @@ libbalsa_message_pathname(LibBalsaMessag
     return message->header->path;
 }
 
+static void libbalsa_message_find_charset(GMimePart *mime_part, gpointer data)
+{
+	const GMimeContentType *type;
+	if (*(gchar **)data)
+		return;
+	type=g_mime_part_get_content_type(mime_part);
+	*(const gchar **)data=g_mime_content_type_get_parameter(type, "charset");
+}
+
 static const gchar *
 libbalsa_message_body_charset(LibBalsaMessageBody * body)
 {
     gchar *charset = NULL;
-
-    while (body) {
-	libbalsa_lock_mutt();
-	charset = mutt_get_parameter("charset", body->mutt_body->parameter);
-	libbalsa_unlock_mutt();
-
-	if (charset)
-	    break;
-	
-	if (body->parts)
-	    charset = (gchar *)libbalsa_message_body_charset(body->parts);
 
-	if (charset)
-	    break;
-
-	body = body->next;
-    }
+	g_mime_part_foreach(body->mime_part,
+			    libbalsa_message_find_charset, &charset);
     return charset;
 }
 
@@ -820,6 +817,9 @@ libbalsa_message_body_ref(LibBalsaMessag
     LibBalsaMessageBody *body;
     HEADER *cur;
     MESSAGE *msg;
+    GMimePart *mime_part;
+    gchar *raw_mime;
+    gint len;
 
     g_return_val_if_fail(message, FALSE);
     if (!message->mailbox) return FALSE;
@@ -844,6 +844,13 @@ libbalsa_message_body_ref(LibBalsaMessag
 	return FALSE;
     }
 
+    fseek(msg->fp, cur->content->hdr_offset, 0);
+    len=cur->content->length+cur->content->offset-cur->content->hdr_offset;
+    raw_mime=g_malloc(len);
+    fread(raw_mime, len, 1, msg->fp);
+    mime_part=g_mime_parser_construct_part(raw_mime, len);
+    g_free(raw_mime);
+    
     fseek(msg->fp, cur->content->offset, 0);
 
     if (cur->content->type == TYPEMULTIPART) {
@@ -881,7 +888,7 @@ libbalsa_message_body_ref(LibBalsaMessag
 		cur->content->type);
 #endif
 	body = libbalsa_message_body_new(message);
-	libbalsa_message_body_set_mutt_body(body, cur->content);
+	libbalsa_message_body_set_mime_body(body, mime_part);
 	libbalsa_message_append_part(message, body);
 
 	message->body_ref++;
Index: libbalsa/mime.c
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/mime.c,v
retrieving revision 1.41
diff -u -b -B -w -p -r1.41 mime.c
--- libbalsa/mime.c	2001/09/23 18:04:48	1.41
+++ libbalsa/mime.c	2001/10/16 22:54:36
@@ -48,6 +48,7 @@ process_mime_part(LibBalsaMessage * mess
     size_t alloced;
     gchar *res = NULL;
     GString *reply = NULL;
+    const GMimeContentType *type;
 
     switch (libbalsa_message_body_type(body)) {
     case LIBBALSA_MESSAGE_BODY_TYPE_OTHER:
@@ -63,20 +64,11 @@ process_mime_part(LibBalsaMessage * mess
                                        llen, ignore_html, flow);
 	break;
     case LIBBALSA_MESSAGE_BODY_TYPE_TEXT:
+	type=g_mime_part_get_content_type(body->mime_part);
 	/* don't return text/html stuff... */
-	if (ignore_html && body->mutt_body->subtype &&
-	    !strcmp("html", body->mutt_body->subtype))
+	if (ignore_html && g_mime_content_type_is_type(type, "*", "html"))
 	    break;
-
-	libbalsa_message_body_save_temporary(body, NULL);
-
-	part = fopen(body->temp_filename, "r");
-	if (!part)
-	    break;
-	alloced = libbalsa_readfile(part, &res);
-	fclose(part);
-	if (!res)
-	    break;
+    res=(gchar*)g_mime_part_get_content(body->mime_part, &alloced);
 
 	if (llen > 0) {
             if (flow && libbalsa_flowed_rfc2646(body)) {
Index: src/Makefile.am
===================================================================
RCS file: /cvs/gnome/balsa/src/Makefile.am,v
retrieving revision 1.105
diff -u -b -B -w -p -r1.105 Makefile.am
--- src/Makefile.am	2001/10/07 19:30:05	1.105
+++ src/Makefile.am	2001/10/16 22:54:54
@@ -71,6 +71,7 @@ balsa_LDADD = \
 	$(top_builddir)/libinit_balsa/libinit_balsa.a \
 	-lpspell \
 	-lltdl \
+	-lgmime \
 	$(INTLLIBS) \
 	$(PCRE_LIBS) \
 	$(PTHREAD_LIB)
Index: src/balsa-message.c
===================================================================
RCS file: /cvs/gnome/balsa/src/balsa-message.c,v
retrieving revision 1.188
diff -u -b -B -w -p -r1.188 balsa-message.c
--- src/balsa-message.c	2001/10/15 22:33:24	1.188
+++ src/balsa-message.c	2001/10/16 22:55:18
@@ -992,8 +992,10 @@ part_info_init_message_extbody_mail(Bals
 static void
 part_info_init_message(BalsaMessage * bm, BalsaPartInfo * info)
 {
-    if (info->body && info->body->mutt_body && info->body->mutt_body->subtype &&
-	!g_strcasecmp("external-body", info->body->mutt_body->subtype)) {
+    const GMimeContentType *type;
+    if (info->body && info->body->mime_part &&
+         (type=g_mime_part_get_content_type(info->body->mime_part)) &&
+         g_mime_content_type_is_type(type, "*", "external-body")) {
 	gchar *access_type;
 	rfc_extbody_id *extbody_type = rfc_extbodys;
 
@@ -2411,18 +2413,19 @@ static void add_body(BalsaMessage *bm, 
 
 
 static void add_multipart(BalsaMessage *bm, LibBalsaMessageBody *parent)
-/* Remarks: *** The tests/assumptions made are NOT verified with the RFCs */
+/* This function handles multiparts as specified by RFC2046 5.1 */
 {
-    if(parent->parts) {
-	gchar *content_type = 
-	    libbalsa_message_body_get_content_type(parent);
-	if(g_strcasecmp(content_type, "multipart/related")==0) {
+    const GMimeContentType *type;
+    type=g_mime_part_get_content_type(parent->mime_part);
+    if (g_mime_content_type_is_type(type, "multipart", "*")) {
+        if (g_mime_content_type_is_type(type, "*", "related")) {
+            /* FIXME: more processing required see RFC1872 */
 	    /* Add the first part */
 	    add_body(bm, parent->parts);
-	} else if(g_strcasecmp(content_type, "multipart/alternative")==0) {
+        } else if (g_mime_content_type_is_type(type, "*", "alternative")) {
 	    /* Add the most suitable part. */
 	    add_body(bm, preferred_part(parent->parts));
-	} else {
+        } else { /* default to multipart/mixed */
 	    /* Add first (main) part + anything else with 
 	       Content-Disposition: inline */
 	    LibBalsaMessageBody *body=parent->parts;
@@ -2430,13 +2433,14 @@ static void add_multipart(BalsaMessage *
 	    if(body) {
 		add_body(bm, body);
 		for(body=body->next; body; body=body->next) {
-		    if(body->mutt_body && 
-		       body->mutt_body->disposition==DISPINLINE)
+                    const gchar *disposition;
+                    disposition=g_mime_part_get_content_disposition(body->mime_part);
+                    if (disposition && g_strcasecmp(disposition, "inline")==0) {
 			add_body(bm, body);
 		}
 	    }
 	}
-	g_free(content_type);
+        }
     }
 }
 
Index: libbalsa/send.c
===================================================================
RCS file: /cvs/gnome/balsa/libbalsa/send.c,v
retrieving revision 1.137
diff -u -b -B -w -p -r1.137 send.c
--- libbalsa/send.c	2001/10/15 22:33:24	1.137
+++ libbalsa/send.c	2001/10/16 22:29:14
@@ -231,34 +231,57 @@ encode_descriptions (BODY *b)
 }
 
 static BODY *
-add_mutt_body_plain(const gchar * charset, gint encoding_style, 
+add_mutt_body_plain(LibBalsaMessageBody *body, gint encoding_style, 
 		    gboolean flow)
 {
-    BODY *body;
+    BODY *mutt_body;
     gchar buffer[PATH_MAX];
+    const gchar * charset;
+    FILE *tempfp = NULL;
 
+    g_return_val_if_fail(body, NULL);
+    charset=body->charset;
     g_return_val_if_fail(charset, NULL);
     libbalsa_lock_mutt();
-    body = mutt_new_body();
+    mutt_body = mutt_new_body();
 
-    body->type = TYPETEXT;
-    body->subtype = g_strdup("plain");
-    body->unlink = 1;
-    body->use_disp = 0;
+    mutt_body->type = TYPETEXT;
+    mutt_body->subtype = g_strdup("plain");
+    mutt_body->unlink = 1;
+    mutt_body->use_disp = 0;
 
-    body->encoding = encoding_style;
+    mutt_body->encoding = encoding_style;
 
-    mutt_set_parameter("charset", charset, &body->parameter);
+    mutt_set_parameter("charset", charset, &mutt_body->parameter);
     if (flow)
-	mutt_set_parameter("format", "flowed", &body->parameter);
+	mutt_set_parameter("format", "flowed", &mutt_body->parameter);
 
     mutt_mktemp(buffer);
-    body->filename = g_strdup(buffer);
-    mutt_update_encoding(body);
+    mutt_body->filename = g_strdup(buffer);
+    mutt_update_encoding(mutt_body);
 
     libbalsa_unlock_mutt();
 
-    return body;
+    if (body->mime_type) {
+        /* change the type and subtype within the mutt body */
+        gchar *type, *subtype;
+
+        type = g_strdup (body->mime_type);
+        if ((subtype = strchr (type, '/'))) {
+            *subtype++ = 0;
+            libbalsa_lock_mutt();
+            mutt_body->type = mutt_check_mime_type (type);
+            g_free(mutt_body->subtype);
+            mutt_body->subtype = g_strdup(subtype);
+            libbalsa_unlock_mutt();
+        }
+        g_free (type);
+    }
+    tempfp = safe_fopen(mutt_body->filename, "w+");
+    fputs(body->buffer, tempfp);
+    fclose(tempfp);
+    tempfp = NULL;
+    return mutt_body;
 }
 
 static BODY *
@@ -1202,7 +1225,6 @@ libbalsa_message_postpone(LibBalsaMessag
 	last = last->next;
 
     while (body) {
-	FILE *tempfp = NULL;
 	newbdy = NULL;
 
 	if (body->filename) {
@@ -1239,25 +1261,7 @@ libbalsa_message_postpone(LibBalsaMessag
 		g_strfreev(mime_type);
 	    }
 	} else if (body->buffer) {
-	    newbdy = add_mutt_body_plain(body->charset, encoding, flow);
-	    if (body->mime_type) {
-		/* change the type and subtype within the mutt body */
-		gchar *type, *subtype;
-		
-		type = g_strdup (body->mime_type);
-		if ((subtype = strchr (type, '/'))) {
-		    *subtype++ = 0;
-		    libbalsa_lock_mutt();
-		    newbdy->type = mutt_check_mime_type (type);
-		    newbdy->subtype = g_strdup(subtype);
-		    libbalsa_unlock_mutt();
-		}
-		g_free (type);
-	    }
-	    tempfp = safe_fopen(newbdy->filename, "w+");
-	    fputs(body->buffer, tempfp);
-	    fclose(tempfp);
-	    tempfp = NULL;
+            newbdy = add_mutt_body_plain(body, encoding, flow);
 	}
 
 	if (newbdy) {
@@ -1395,7 +1399,6 @@ libbalsa_create_msg(LibBalsaMessage * me
 	last = last->next;
 
     while (body) {
-	FILE *tempfp = NULL;
 	newbdy = NULL;
 
 	if (body->filename) {
@@ -1439,29 +1442,7 @@ libbalsa_create_msg(LibBalsaMessage * me
 		}
 	    }
 	} else if (body->buffer) {
-	    newbdy = add_mutt_body_plain(body->charset, encoding, flow);
-	    if (body->mime_type) {
-		/* change the type and subtype within the mutt body */
-		gchar *type, *subtype;
-		
-		type = g_strdup (body->mime_type);
-		if ((subtype = strchr (type, '/'))) {
-		    *subtype++ = 0;
-		    libbalsa_lock_mutt();
-		    newbdy->type = mutt_check_mime_type (type);
-		    g_free(newbdy->subtype);
-		    newbdy->subtype = g_strdup(subtype);
-		    libbalsa_unlock_mutt();
-		}
-		g_free (type);
-	    }
-	    tempfp = safe_fopen(newbdy->filename, "w+");
-	    fputs(body->buffer, tempfp);
-	    fclose(tempfp);
-	    tempfp = NULL;
+	    newbdy = add_mutt_body_plain(body, encoding, flow);
- 	} else {
-	    /* safe_free bug patch: steal it! */
-	    msg->content = mutt_copy_body(body->mutt_body, NULL);
 	}
 
 	if (newbdy) {


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