gmime r1427 - in trunk: . gmime



Author: fejj
Date: Sat Sep  6 14:39:15 2008
New Revision: 1427
URL: http://svn.gnome.org/viewvc/gmime?rev=1427&view=rev

Log:
2008-09-06  Jeffrey Stedfast  <fejj novell com>

	* gmime/gmime-part.c (g_mime_part_set_content_object): Made
	virtual, seems like it could be useful.

	* gmime/gmime-object.c (set_content_type): Do not serialize the
	GMimeContentType object to the headers. This is done elsewhere
	now.
	(g_mime_object_set_content_type): After calling the virtual
	set_content_type(), serialize the GMimeContentType object to the
	headers.

	* gmime/gmime-multipart-encrypted.c: Get rid of the protocol
	member variable, it's not needed.

	* gmime/gmime-multipart-signed.c: Get rid of the protocol and
	micalg member strings, these aren't needed - just request them
	from the content_type.

	* gmime/gmime-multipart.c: Get rid of boundary member variable, we
	can just request it from the ContentType object. No sense
	duplicating strings.

	* gmime/gmime-message.c (message_get_headers): Don't write out a
	MIME-Version header if a Content-Type header doesn't exist.

	* gmime/gmime-parser.c (parser_content_type): Instead of returning
	a GMimeContentType object, we now return a simpler ContentType
	struct so that we don't waste time processing more of the header
	than we need to, all we need is the type/subtype to figure out
	which MIME object type to instantiate.
	(parser_scan_message_part): After finishing parsing the object,
	destroy the content_type ourselves.
	(parser_construct_leaf_part): Updated. Don't set a
	GMimeContentType on the GMimeObject unless the Content-Type header
	doesn't exist (if it does exist, then appending the Content-Type
	header will cause one to be created and set on the GMimeObject).
	(parser_construct_multipart): Updated.

	* gmime/gmime-content-type.c (g_mime_content_type_new_from_string):
	Use the new g_mime_parse_content_type() utility function and set
	the parsed string values on the new GMimeContentType object
	directly to avoid unnecessary strdup()ing.

	* gmime/gmime-parse-utils.c (g_mime_parse_content_type): New
	function to parse the simple type/subtype Content-Type form.




Modified:
   trunk/ChangeLog
   trunk/gmime/gmime-content-type.c
   trunk/gmime/gmime-message.c
   trunk/gmime/gmime-multipart-encrypted.c
   trunk/gmime/gmime-multipart-encrypted.h
   trunk/gmime/gmime-multipart-signed.c
   trunk/gmime/gmime-multipart-signed.h
   trunk/gmime/gmime-multipart.c
   trunk/gmime/gmime-object.c
   trunk/gmime/gmime-object.h
   trunk/gmime/gmime-parse-utils.c
   trunk/gmime/gmime-parse-utils.h
   trunk/gmime/gmime-parser.c
   trunk/gmime/gmime-part.c
   trunk/gmime/gmime-part.h

Modified: trunk/gmime/gmime-content-type.c
==============================================================================
--- trunk/gmime/gmime-content-type.c	(original)
+++ trunk/gmime/gmime-content-type.c	Sat Sep  6 14:39:15 2008
@@ -194,45 +194,20 @@
 g_mime_content_type_new_from_string (const char *str)
 {
 	GMimeContentType *mime_type;
-	char *type = NULL, *subtype;
 	const char *inptr = str;
+	char *type, *subtype;
 	
 	g_return_val_if_fail (str != NULL, NULL);
 	
-	/* get the type */
-	type = (char *) inptr;
-	while (*inptr && is_ttoken (*inptr))
-		inptr++;
-	
-	type = g_strndup (type, (unsigned) (inptr - type));
+	if (!g_mime_parse_content_type (&inptr, &type, &subtype))
+		return g_mime_content_type_new ("application", "octet-stream");
 	
-	decode_lwsp (&inptr);
-	
-	/* get the subtype */
-	if (*inptr == '/') {
-		inptr++;
-		
-		decode_lwsp (&inptr);
-		
-		subtype = (char *) inptr;
-		while (*inptr && is_ttoken (*inptr))
-			inptr++;
-		
-		if (inptr > subtype)
-			subtype = g_strndup (subtype, (size_t) (inptr - subtype));
-		else
-			subtype = NULL;
-		
-		decode_lwsp (&inptr);
-	} else {
-		subtype = NULL;
-	}
-	
-	mime_type = g_mime_content_type_new (type, subtype);
-	g_free (subtype);
-	g_free (type);
+	mime_type = g_object_new (GMIME_TYPE_CONTENT_TYPE, NULL);
+	mime_type->subtype = subtype;
+	mime_type->type = type;
 	
 	/* skip past any remaining junk that shouldn't be here... */
+	decode_lwsp (&inptr);
 	while (*inptr && *inptr != ';')
 		inptr++;
 	

Modified: trunk/gmime/gmime-message.c
==============================================================================
--- trunk/gmime/gmime-message.c	(original)
+++ trunk/gmime/gmime-message.c	Sat Sep  6 14:39:15 2008
@@ -948,7 +948,8 @@
 	} else {
 		g_mime_header_list_write_to_stream (object->headers, stream);
 		if (message->mime_part) {
-			g_mime_stream_write_string (stream, "MIME-Version: 1.0\n");
+			if (g_mime_object_get_header (message->mime_part, "Content-Type"))
+				g_mime_stream_write_string (stream, "MIME-Version: 1.0\n");
 			g_mime_header_list_write_to_stream (message->mime_part->headers, stream);
 		}
 	}

Modified: trunk/gmime/gmime-multipart-encrypted.c
==============================================================================
--- trunk/gmime/gmime-multipart-encrypted.c	(original)
+++ trunk/gmime/gmime-multipart-encrypted.c	Sat Sep  6 14:39:15 2008
@@ -119,7 +119,6 @@
 static void
 g_mime_multipart_encrypted_init (GMimeMultipartEncrypted *mpe, GMimeMultipartEncryptedClass *klass)
 {
-	mpe->protocol = NULL;
 	mpe->decrypted = NULL;
 	mpe->validity = NULL;
 }
@@ -129,8 +128,6 @@
 {
 	GMimeMultipartEncrypted *mpe = (GMimeMultipartEncrypted *) object;
 	
-	g_free (mpe->protocol);
-	
 	if (mpe->decrypted)
 		g_object_unref (mpe->decrypted);
 	
@@ -173,13 +170,6 @@
 static void
 multipart_encrypted_set_content_type (GMimeObject *object, GMimeContentType *content_type)
 {
-	GMimeMultipartEncrypted *mpe = (GMimeMultipartEncrypted *) object;
-	const char *protocol;
-	
-	protocol = g_mime_content_type_get_parameter (content_type, "protocol");
-	g_free (mpe->protocol);
-	mpe->protocol = g_strdup (protocol);
-	
 	GMIME_OBJECT_CLASS (parent_class)->set_content_type (object, content_type);
 }
 
@@ -295,7 +285,6 @@
 	g_object_unref (wrapper);
 	g_object_unref (stream);
 	
-	mpe->protocol = g_strdup (ctx->encrypt_protocol);
 	mpe->decrypted = content;
 	g_object_ref (content);
 	
@@ -315,7 +304,8 @@
 	g_object_unref (version_part);
 	
 	/* set the content-type params for this multipart/encrypted part */
-	g_mime_object_set_content_type_parameter (GMIME_OBJECT (mpe), "protocol", mpe->protocol);
+	g_mime_object_set_content_type_parameter (GMIME_OBJECT (mpe), "protocol",
+						  ctx->encrypt_protocol);
 	g_mime_multipart_set_boundary (GMIME_MULTIPART (mpe), NULL);
 	
 	return 0;

Modified: trunk/gmime/gmime-multipart-encrypted.h
==============================================================================
--- trunk/gmime/gmime-multipart-encrypted.h	(original)
+++ trunk/gmime/gmime-multipart-encrypted.h	Sat Sep  6 14:39:15 2008
@@ -48,7 +48,6 @@
  * @parent_object: parent #GMimeMultipart
  * @validity: a #GMimeSignatureValidity if the part has been decrypted or %NULL otherwise
  * @decrypted: cached decrypted MIME part
- * @protocol: encryption protocol string
  *
  * A multipart/encrypted MIME part.
  **/
@@ -57,7 +56,6 @@
 	
 	GMimeSignatureValidity *validity;
 	GMimeObject *decrypted;
-	char *protocol;
 };
 
 struct _GMimeMultipartEncryptedClass {

Modified: trunk/gmime/gmime-multipart-signed.c
==============================================================================
--- trunk/gmime/gmime-multipart-signed.c	(original)
+++ trunk/gmime/gmime-multipart-signed.c	Sat Sep  6 14:39:15 2008
@@ -119,8 +119,7 @@
 static void
 g_mime_multipart_signed_init (GMimeMultipartSigned *mps, GMimeMultipartSignedClass *klass)
 {
-	mps->protocol = NULL;
-	mps->micalg = NULL;
+	
 }
 
 static void
@@ -128,9 +127,6 @@
 {
 	GMimeMultipartSigned *mps = (GMimeMultipartSigned *) object;
 	
-	g_free (mps->protocol);
-	g_free (mps->micalg);
-	
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -167,17 +163,6 @@
 static void
 multipart_signed_set_content_type (GMimeObject *object, GMimeContentType *content_type)
 {
-	GMimeMultipartSigned *mps = (GMimeMultipartSigned *) object;
-	const char *protocol, *micalg;
-	
-	protocol = g_mime_content_type_get_parameter (content_type, "protocol");
-	g_free (mps->protocol);
-	mps->protocol = g_strdup (protocol);
-	
-	micalg = g_mime_content_type_get_parameter (content_type, "micalg");
-	g_free (mps->micalg);
-	mps->micalg = g_strdup (micalg);
-	
 	GMIME_OBJECT_CLASS (parent_class)->set_content_type (object, content_type);
 }
 
@@ -289,6 +274,7 @@
 	GMimePart *signature;
 	GMimeFilter *filter;
 	GMimeParser *parser;
+	const char *micalg;
 	int rv;
 	
 	g_return_val_if_fail (GMIME_IS_MULTIPART_SIGNED (mps), -1);
@@ -340,10 +326,10 @@
 	g_mime_stream_reset (stream);
 	
 	/* set the multipart/signed protocol and micalg */
-	mps->protocol = g_strdup (ctx->sign_protocol);
-	mps->micalg = g_strdup (g_mime_cipher_context_hash_name (ctx, (GMimeCipherHash) rv));
-	g_mime_object_set_content_type_parameter (GMIME_OBJECT (mps), "protocol", mps->protocol);
-	g_mime_object_set_content_type_parameter (GMIME_OBJECT (mps), "micalg", mps->micalg);
+	content_type = g_mime_object_get_content_type (GMIME_OBJECT (mps));
+	g_mime_content_type_set_parameter (content_type, "protocol", ctx->sign_protocol);
+	micalg = g_strdup (g_mime_cipher_context_hash_name (ctx, (GMimeCipherHash) rv));
+	g_mime_content_type_set_parameter (content_type, "micalg", micalg);
 	g_mime_multipart_set_boundary (GMIME_MULTIPART (mps), NULL);
 	
 	/* construct the content part */
@@ -353,7 +339,7 @@
 	g_object_unref (parser);
 	
 	/* construct the signature part */
-	content_type = g_mime_content_type_new_from_string (mps->protocol);
+	content_type = g_mime_content_type_new_from_string (ctx->sign_protocol);
 	signature = g_mime_part_new_with_type (content_type->type, content_type->subtype);
 	g_object_unref (content_type);
 	
@@ -366,7 +352,7 @@
 	/* FIXME: temporary hack, this info should probably be set in
 	 * the CipherContext class - maybe ::sign can take/output a
 	 * GMimePart instead. */
-	if (!g_ascii_strcasecmp (mps->protocol, "application/pkcs7-signature")) {
+	if (!g_ascii_strcasecmp (ctx->sign_protocol, "application/pkcs7-signature")) {
 		g_mime_part_set_content_encoding (signature, GMIME_CONTENT_ENCODING_BASE64);
 		g_mime_part_set_filename (signature, "smime.p7m");
 	}
@@ -475,7 +461,7 @@
 	g_mime_stream_reset (sigstream);
 	
 	/* verify the signature */
-	hash = g_mime_cipher_context_hash_id (ctx, mps->micalg);
+	hash = g_mime_cipher_context_hash_id (ctx, micalg);
 	valid = g_mime_cipher_context_verify (ctx, hash, stream, sigstream, err);
 	
 	d(printf ("attempted to verify:\n----- BEGIN SIGNED PART -----\n%.*s----- END SIGNED PART -----\n",

Modified: trunk/gmime/gmime-multipart-signed.h
==============================================================================
--- trunk/gmime/gmime-multipart-signed.h	(original)
+++ trunk/gmime/gmime-multipart-signed.h	Sat Sep  6 14:39:15 2008
@@ -46,16 +46,12 @@
 /**
  * GMimeMultipartSigned:
  * @parent_object: parent #GMimeMultipart
- * @protocol: signature protocol string
- * @micalg: signature hash
  *
  * A multipart/signed MIME part.
  **/
 struct _GMimeMultipartSigned {
 	GMimeMultipart parent_object;
 	
-	char *protocol;
-	char *micalg;
 };
 
 struct _GMimeMultipartSignedClass {

Modified: trunk/gmime/gmime-multipart.c
==============================================================================
--- trunk/gmime/gmime-multipart.c	(original)
+++ trunk/gmime/gmime-multipart.c	Sat Sep  6 14:39:15 2008
@@ -140,7 +140,6 @@
 g_mime_multipart_init (GMimeMultipart *multipart, GMimeMultipartClass *klass)
 {
 	multipart->children = g_ptr_array_new ();
-	multipart->boundary = NULL;
 	multipart->preface = NULL;
 	multipart->postface = NULL;
 }
@@ -151,7 +150,6 @@
 	GMimeMultipart *multipart = (GMimeMultipart *) object;
 	guint i;
 	
-	g_free (multipart->boundary);
 	g_free (multipart->preface);
 	g_free (multipart->postface);
 	
@@ -219,13 +217,6 @@
 static void
 multipart_set_content_type (GMimeObject *object, GMimeContentType *content_type)
 {
-	GMimeMultipart *multipart = (GMimeMultipart *) object;
-	const char *boundary;
-	
-	boundary = g_mime_content_type_get_parameter (content_type, "boundary");
-	g_free (multipart->boundary);
-	multipart->boundary = g_strdup (boundary);
-	
 	GMIME_OBJECT_CLASS (parent_class)->set_content_type (object, content_type);
 }
 
@@ -240,6 +231,7 @@
 {
 	GMimeMultipart *multipart = (GMimeMultipart *) object;
 	ssize_t nwritten, total = 0;
+	const char *boundary;
 	GMimeObject *part;
 	guint i;
 	
@@ -247,8 +239,11 @@
 	 * 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) */
-	if (!multipart->boundary && !g_mime_header_list_has_raw (object->headers))
+	boundary = g_mime_object_get_content_type_parameter (object, "boundary");
+	if (!boundary && !g_mime_header_list_has_raw (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)
@@ -274,7 +269,7 @@
 		part = multipart->children->pdata[i];
 		
 		/* write the boundary */
-		if ((nwritten = g_mime_stream_printf (stream, "\n--%s\n", multipart->boundary)) == -1)
+		if ((nwritten = g_mime_stream_printf (stream, "\n--%s\n", boundary)) == -1)
 			return -1;
 		
 		total += nwritten;
@@ -287,8 +282,8 @@
 	}
 	
 	/* write the end-boundary (but only if a boundary is set) */
-	if (multipart->boundary) {
-		if ((nwritten = g_mime_stream_printf (stream, "\n--%s--\n", multipart->boundary)) == -1)
+	if (boundary) {
+		if ((nwritten = g_mime_stream_printf (stream, "\n--%s--\n", boundary)) == -1)
 			return -1;
 		
 		total += nwritten;
@@ -763,9 +758,6 @@
 		boundary = bbuf;
 	}
 	
-	g_free (multipart->boundary);
-	multipart->boundary = g_strdup (boundary);
-	
 	g_mime_object_set_content_type_parameter (GMIME_OBJECT (multipart), "boundary", boundary);
 }
 
@@ -790,10 +782,15 @@
 static const char *
 multipart_get_boundary (GMimeMultipart *multipart)
 {
-	if (!multipart->boundary)
-		multipart_set_boundary (multipart, NULL);
+	GMimeObject *object = (GMimeObject *) multipart;
+	const char *boundary;
+	
+	if ((boundary = g_mime_object_get_content_type_parameter (object, "boundary")))
+		return boundary;
+	
+	multipart_set_boundary (multipart, NULL);
 	
-	return multipart->boundary;
+	return g_mime_object_get_content_type_parameter (object, "boundary");
 }
 
 

Modified: trunk/gmime/gmime-object.c
==============================================================================
--- trunk/gmime/gmime-object.c	(original)
+++ trunk/gmime/gmime-object.c	Sat Sep  6 14:39:15 2008
@@ -54,6 +54,9 @@
 	GType object_type;
 };
 
+static void _g_mime_object_set_content_disposition (GMimeObject *object, GMimeContentDisposition *disposition);
+void _g_mime_object_set_content_type (GMimeObject *object, GMimeContentType *content_type);
+
 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);
@@ -292,26 +295,6 @@
 	g_hash_table_insert (bucket->subtype_hash, sub->subtype, sub);
 }
 
-static void
-set_content_type_internal (GMimeObject *object, GMimeContentType *content_type, gboolean resync)
-{
-	if (content_type == object->content_type)
-		return;
-	
-	if (object->content_type) {
-		g_signal_handlers_disconnect_matched (object->content_type,
-						      G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
-						      0, 0, NULL, content_type_changed, object);
-		g_object_unref (object->content_type);
-	}
-	
-	g_signal_connect (content_type, "changed", G_CALLBACK (content_type_changed), object);
-	object->content_type = content_type;
-	g_object_ref (content_type);
-	
-	if (resync)
-		content_type_changed (content_type, object);
-}
 
 /**
  * g_mime_object_new:
@@ -426,24 +409,56 @@
 static void
 set_content_type (GMimeObject *object, GMimeContentType *content_type)
 {
-	set_content_type_internal (object, content_type, TRUE);
+	if (object->content_type) {
+		g_signal_handlers_disconnect_matched (object->content_type,
+						      G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
+						      0, 0, NULL, content_type_changed, object);
+		g_object_unref (object->content_type);
+	}
+	
+	g_signal_connect (content_type, "changed", G_CALLBACK (content_type_changed), object);
+	object->content_type = content_type;
+	g_object_ref (content_type);
 }
 
 
 /**
- * g_mime_object_set_content_type:
+ * _g_mime_object_set_content_type:
  * @object: a #GMimeObject
- * @mime_type: a #GMimeContentType object
+ * @content_type: a #GMimeContentType object
  *
  * Sets the content-type for the specified MIME object.
+ *
+ * Note: This method is meant for internal-use only and avoids
+ * serialization of @content_type to the Content-Type header field.
  **/
 void
-g_mime_object_set_content_type (GMimeObject *object, GMimeContentType *mime_type)
+_g_mime_object_set_content_type (GMimeObject *object, GMimeContentType *content_type)
 {
-	g_return_if_fail (GMIME_IS_CONTENT_TYPE (mime_type));
+	GMIME_OBJECT_GET_CLASS (object)->set_content_type (object, content_type);
+}
+
+
+/**
+ * g_mime_object_set_content_type:
+ * @object: a #GMimeObject
+ * @content_type: a #GMimeContentType object
+ *
+ * Sets the content-type for the specified MIME object and then
+ * serializes it to the Content-Type header field.
+ **/
+void
+g_mime_object_set_content_type (GMimeObject *object, GMimeContentType *content_type)
+{
+	g_return_if_fail (GMIME_IS_CONTENT_TYPE (content_type));
 	g_return_if_fail (GMIME_IS_OBJECT (object));
 	
-	GMIME_OBJECT_GET_CLASS (object)->set_content_type (object, mime_type);
+	if (object->content_type == content_type)
+		return;
+	
+	GMIME_OBJECT_GET_CLASS (object)->set_content_type (object, content_type);
+	
+	content_type_changed (content_type, object);
 }
 
 
@@ -520,13 +535,20 @@
 	return object->disposition;
 }
 
-
+/**
+ * g_mime_object_set_content_disposition:
+ * @object: a #GMimeObject
+ * @disposition: a #GMimeContentDisposition object
+ *
+ * Set the content disposition for the specified mime part.
+ *
+ * Note: This method is meant for internal-use only and avoids
+ * serialization of @disposition to the Content-Disposition header
+ * field.
+ **/
 static void
-set_content_disposition_internal (GMimeObject *object, GMimeContentDisposition *disposition, gboolean resync)
+_g_mime_object_set_content_disposition (GMimeObject *object, GMimeContentDisposition *disposition)
 {
-	if (disposition == object->disposition)
-		return;
-	
 	if (object->disposition) {
 		g_signal_handlers_disconnect_matched (object->disposition,
 						      G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
@@ -537,17 +559,16 @@
 	g_signal_connect (disposition, "changed", G_CALLBACK (content_disposition_changed), object);
 	object->disposition = disposition;
 	g_object_ref (disposition);
-	
-	if (resync)
-		content_disposition_changed (disposition, object);
 }
 
+
 /**
  * g_mime_object_set_content_disposition:
  * @object: a #GMimeObject
  * @disposition: a #GMimeContentDisposition object
  *
- * Set the content disposition for the specified mime part.
+ * Set the content disposition for the specified mime part and then
+ * serializes it to the Content-Disposition header field.
  **/
 void
 g_mime_object_set_content_disposition (GMimeObject *object, GMimeContentDisposition *disposition)
@@ -555,7 +576,12 @@
 	g_return_if_fail (GMIME_IS_CONTENT_DISPOSITION (disposition));
 	g_return_if_fail (GMIME_IS_OBJECT (object));
 	
-	set_content_disposition_internal (object, disposition, TRUE);
+	if (object->disposition == disposition)
+		return;
+	
+	_g_mime_object_set_content_disposition (object, disposition);
+	
+	content_disposition_changed (disposition, object);
 }
 
 
@@ -628,7 +654,7 @@
 	
 	if (!object->disposition) {
 		disposition = g_mime_content_disposition_new ();
-		set_content_disposition_internal (object, disposition, FALSE);
+		_g_mime_object_set_content_disposition (object, disposition);
 	}
 	
 	g_mime_content_disposition_set_parameter (object->disposition, attribute, value);
@@ -727,12 +753,12 @@
 	switch (i) {
 	case HEADER_CONTENT_DISPOSITION:
 		disposition = g_mime_content_disposition_new_from_string (value);
-		set_content_disposition_internal (object, disposition, FALSE);
+		_g_mime_object_set_content_disposition (object, disposition);
 		g_object_unref (disposition);
 		break;
 	case HEADER_CONTENT_TYPE:
 		content_type = g_mime_content_type_new_from_string (value);
-		set_content_type_internal (object, content_type, FALSE);
+		_g_mime_object_set_content_type (object, content_type);
 		g_object_unref (content_type);
 		break;
 	case HEADER_CONTENT_ID:

Modified: trunk/gmime/gmime-object.h
==============================================================================
--- trunk/gmime/gmime-object.h	(original)
+++ trunk/gmime/gmime-object.h	Sat Sep  6 14:39:15 2008
@@ -97,7 +97,7 @@
 GMimeObject *g_mime_object_new (GMimeContentType *content_type);
 GMimeObject *g_mime_object_new_type (const char *type, const char *subtype);
 
-void g_mime_object_set_content_type (GMimeObject *object, GMimeContentType *mime_type);
+void g_mime_object_set_content_type (GMimeObject *object, GMimeContentType *content_type);
 GMimeContentType *g_mime_object_get_content_type (GMimeObject *object);
 void g_mime_object_set_content_type_parameter (GMimeObject *object, const char *name, const char *value);
 const char *g_mime_object_get_content_type_parameter (GMimeObject *object, const char *name);

Modified: trunk/gmime/gmime-parse-utils.c
==============================================================================
--- trunk/gmime/gmime-parse-utils.c	(original)
+++ trunk/gmime/gmime-parse-utils.c	Sat Sep  6 14:39:15 2008
@@ -39,6 +39,68 @@
 
 
 /**
+ * g_mime_parse_content_type:
+ * @in: address of input text string
+ * @type: address of the 'type' output string
+ * @subtype: address of the 'subtype' output string
+ *
+ * Decodes the simple Content-Type type/subtype tokens and updates @in
+ * to point to the first char after the end of the subtype.
+ *
+ * Returns: %TRUE if the string was successfully parsed or %FALSE
+ * otherwise.
+ **/
+gboolean
+g_mime_parse_content_type (const char **in, char **type, char **subtype)
+{
+	register const char *inptr;
+	const char *start = *in;
+	
+	decode_lwsp (&start);
+	inptr = start;
+	
+	/* decode the type */
+	while (*inptr && is_ttoken (*inptr))
+		inptr++;
+	
+	*type = g_strndup (start, (size_t) (inptr - start));
+	
+	start = inptr;
+	decode_lwsp (&start);
+	
+	/* check for type/subtype delimeter */
+	if (*start++ != '/') {
+		g_free (*type);
+		*subtype = NULL;
+		*type = NULL;
+		return FALSE;
+	}
+	
+	decode_lwsp (&start);
+	inptr = start;
+	
+	/* decode the subtype */
+	while (*inptr && is_ttoken (*inptr))
+		inptr++;
+	
+	/* check that the subtype exists */
+	if (inptr == start) {
+		g_free (*type);
+		*subtype = NULL;
+		*type = NULL;
+		return FALSE;
+	}
+	
+	*subtype = g_strndup (start, (size_t) (inptr - start));
+	
+	/* update the input string pointer */
+	*in = inptr;
+	
+	return TRUE;
+}
+
+
+/**
  * g_mime_decode_lwsp:
  * @in: address of input text string
  *

Modified: trunk/gmime/gmime-parse-utils.h
==============================================================================
--- trunk/gmime/gmime-parse-utils.h	(original)
+++ trunk/gmime/gmime-parse-utils.h	Sat Sep  6 14:39:15 2008
@@ -24,6 +24,8 @@
 
 G_BEGIN_DECLS
 
+gboolean g_mime_parse_content_type (const char **in, char **type, char **subtype);
+
 void g_mime_decode_lwsp (const char **in);
 #define decode_lwsp(in) g_mime_decode_lwsp (in)
 

Modified: trunk/gmime/gmime-parser.c
==============================================================================
--- trunk/gmime/gmime-parser.c	(original)
+++ trunk/gmime/gmime-parser.c	Sat Sep  6 14:39:15 2008
@@ -57,6 +57,13 @@
  **/
 
 
+typedef struct _ContentType {
+	char *type, *subtype;
+	gboolean exists;
+} ContentType;
+
+extern void _g_mime_object_set_content_type (GMimeObject *object, GMimeContentType *content_type);
+
 static void g_mime_parser_class_init (GMimeParserClass *klass);
 static void g_mime_parser_init (GMimeParser *parser, GMimeParserClass *klass);
 static void g_mime_parser_finalize (GObject *object);
@@ -64,9 +71,9 @@
 static void parser_init (GMimeParser *parser, GMimeStream *stream);
 static void parser_close (GMimeParser *parser);
 
-static GMimeObject *parser_construct_leaf_part (GMimeParser *parser, GMimeContentType *content_type,
+static GMimeObject *parser_construct_leaf_part (GMimeParser *parser, ContentType *content_type,
 						int *found);
-static GMimeObject *parser_construct_multipart (GMimeParser *parser, GMimeContentType *content_type,
+static GMimeObject *parser_construct_multipart (GMimeParser *parser, ContentType *content_type,
 						int *found);
 
 static GObjectClass *parent_class = NULL;
@@ -125,7 +132,6 @@
 	unsigned short int persist_stream:1;
 	unsigned short int respect_content_length:1;
 	
-	GMimeContentType *content_type;
 	struct _header_raw *headers;
 	
 	struct _boundary_stack *bounds;
@@ -1029,16 +1035,49 @@
 	return 0;
 }
 
-static GMimeContentType *
+static void
+content_type_destroy (ContentType *content_type)
+{
+	g_free (content_type->subtype);
+	g_free (content_type->type);
+	g_free (content_type);
+}
+
+static gboolean
+content_type_is_type (ContentType *content_type, const char *type, const char *subtype)
+{
+	if (!strcmp (type, "*") || !g_ascii_strcasecmp (content_type->type, type)) {
+		if (!strcmp (subtype, "*")) {
+			/* special case */
+			return TRUE;
+		}
+		
+		if (!g_ascii_strcasecmp (content_type->subtype, subtype))
+			return TRUE;
+	}
+	
+	return FALSE;
+}
+
+static ContentType *
 parser_content_type (GMimeParser *parser)
 {
 	struct _GMimeParserPrivate *priv = parser->priv;
-	const char *content_type;
+	register const char *inptr;
+	ContentType *content_type;
+	const char *value;
 	
-	if ((content_type = header_raw_find (priv->headers, "Content-Type", NULL)))
-		return g_mime_content_type_new_from_string (content_type);
+	content_type = g_new (ContentType, 1);
 	
-	return NULL;
+	if (!(value = header_raw_find (priv->headers, "Content-Type", NULL)) ||
+	    !g_mime_parse_content_type (&value, &content_type->type, &content_type->subtype)) {
+		content_type->type = g_strdup ("text");
+		content_type->subtype = g_strdup ("plain");
+	}
+	
+	content_type->exists = value != NULL;
+	
+	return content_type;
 }
 
 static int
@@ -1320,8 +1359,8 @@
 parser_scan_message_part (GMimeParser *parser, GMimeMessagePart *mpart, int *found)
 {
 	struct _GMimeParserPrivate *priv = parser->priv;
-	GMimeContentType *content_type;
 	struct _header_raw *header;
+	ContentType *content_type;
 	GMimeMessage *message;
 	GMimeObject *object;
 	
@@ -1343,14 +1382,13 @@
 		header = header->next;
 	}
 	
-	if (!(content_type = parser_content_type (parser)))
-		content_type = g_mime_content_type_new ("text", "plain");
-	
-	if (g_mime_content_type_is_type (content_type, "multipart", "*"))
+	content_type = parser_content_type (parser);
+	if (content_type_is_type (content_type, "multipart", "*"))
 		object = parser_construct_multipart (parser, content_type, found);
 	else
 		object = parser_construct_leaf_part (parser, content_type, found);
 	
+	content_type_destroy (content_type);
 	message->mime_part = object;
 	
 	g_mime_message_part_set_message (mpart, message);
@@ -1358,7 +1396,7 @@
 }
 
 static GMimeObject *
-parser_construct_leaf_part (GMimeParser *parser, GMimeContentType *content_type, int *found)
+parser_construct_leaf_part (GMimeParser *parser, ContentType *content_type, int *found)
 {
 	struct _GMimeParserPrivate *priv = parser->priv;
 	struct _header_raw *header;
@@ -1368,6 +1406,14 @@
 	
 	object = g_mime_object_new_type (content_type->type, content_type->subtype);
 	
+	if (!content_type->exists) {
+		GMimeContentType *mime_type;
+		
+		mime_type = g_mime_content_type_new ("text", "plain");
+		_g_mime_object_set_content_type (object, mime_type);
+		g_object_unref (mime_type);
+	}
+	
 	header = priv->headers;
 	while (header) {
 		g_mime_object_append_header (object, header->name, header->value);
@@ -1376,9 +1422,6 @@
 	
 	header_raw_clear (&priv->headers);
 	
-	g_mime_object_set_content_type (object, content_type);
-	g_object_unref (content_type);
-	
 	g_mime_header_list_set_raw (object->headers, priv->rawbuf);
 	raw_header_reset (priv);
 	
@@ -1468,7 +1511,7 @@
 parser_scan_multipart_subparts (GMimeParser *parser, GMimeMultipart *multipart)
 {
 	struct _GMimeParserPrivate *priv = parser->priv;
-	GMimeContentType *content_type;
+	ContentType *content_type;
 	GMimeObject *subpart;
 	int found;
 	
@@ -1491,15 +1534,14 @@
 			break;
 		}
 		
-		if (!(content_type = parser_content_type (parser)))
-			content_type = g_mime_content_type_new ("text", "plain");
-		
-		if (g_mime_content_type_is_type (content_type, "multipart", "*"))
+		content_type = parser_content_type (parser);
+		if (content_type_is_type (content_type, "multipart", "*"))
 			subpart = parser_construct_multipart (parser, content_type, &found);
 		else
 			subpart = parser_construct_leaf_part (parser, content_type, &found);
 		
 		g_mime_multipart_add (multipart, subpart);
+		content_type_destroy (content_type);
 		g_object_unref (subpart);
 	} while (found == FOUND_BOUNDARY && found_immediate_boundary (priv, FALSE));
 	
@@ -1507,7 +1549,7 @@
 }
 
 static GMimeObject *
-parser_construct_multipart (GMimeParser *parser, GMimeContentType *content_type, int *found)
+parser_construct_multipart (GMimeParser *parser, ContentType *content_type, int *found)
 {
 	struct _GMimeParserPrivate *priv = parser->priv;
 	struct _header_raw *header;
@@ -1527,9 +1569,6 @@
 	
 	header_raw_clear (&priv->headers);
 	
-	g_mime_object_set_content_type (object, content_type);
-	g_object_unref (content_type);
-	
 	g_mime_header_list_set_raw (object->headers, priv->rawbuf);
 	raw_header_reset (priv);
 	
@@ -1543,7 +1582,7 @@
 		}
 	}
 	
-	boundary = g_mime_content_type_get_parameter (content_type, "boundary");
+	boundary = g_mime_object_get_content_type_parameter (object, "boundary");
 	if (boundary) {
 		parser_push_boundary (parser, boundary);
 		
@@ -1573,7 +1612,7 @@
 parser_construct_part (GMimeParser *parser)
 {
 	struct _GMimeParserPrivate *priv = parser->priv;
-	GMimeContentType *content_type;
+	ContentType *content_type;
 	GMimeObject *object;
 	int found;
 	
@@ -1583,14 +1622,14 @@
 			return NULL;
 	}
 	
-	if (!(content_type = parser_content_type (parser)))
-		content_type = g_mime_content_type_new ("text", "plain");
-	
-	if (g_mime_content_type_is_type (content_type, "multipart", "*"))
+	content_type = parser_content_type (parser);
+	if (content_type_is_type (content_type, "multipart", "*"))
 		object = parser_construct_multipart (parser, content_type, &found);
 	else
 		object = parser_construct_leaf_part (parser, content_type, &found);
 	
+	content_type_destroy (content_type);
+	
 	return object;
 }
 
@@ -1617,8 +1656,8 @@
 {
 	struct _GMimeParserPrivate *priv = parser->priv;
 	unsigned long content_length = ULONG_MAX;
-	GMimeContentType *content_type;
 	struct _header_raw *header;
+	ContentType *content_type;
 	GMimeMessage *message;
 	GMimeObject *object;
 	char *endptr;
@@ -1655,14 +1694,13 @@
 			priv->bounds->content_end = parser_offset (priv, NULL) + content_length;
 	}
 	
-	if (!(content_type = parser_content_type (parser)))
-		content_type = g_mime_content_type_new ("text", "plain");
-	
-	if (content_type && g_mime_content_type_is_type (content_type, "multipart", "*"))
+	content_type = parser_content_type (parser);
+	if (content_type_is_type (content_type, "multipart", "*"))
 		object = parser_construct_multipart (parser, content_type, &found);
 	else
 		object = parser_construct_leaf_part (parser, content_type, &found);
 	
+	content_type_destroy (content_type);
 	message->mime_part = object;
 	
 	if (priv->scan_from) {

Modified: trunk/gmime/gmime-part.c
==============================================================================
--- trunk/gmime/gmime-part.c	(original)
+++ trunk/gmime/gmime-part.c	Sat Sep  6 14:39:15 2008
@@ -67,6 +67,9 @@
 static char *mime_part_get_headers (GMimeObject *object);
 static ssize_t mime_part_write_to_stream (GMimeObject *object, GMimeStream *stream);
 
+/* GMimePart class methods */
+static void set_content_object (GMimePart *mime_part, GMimeDataWrapper *content);
+
 
 static GMimeObjectClass *parent_class = NULL;
 
@@ -113,6 +116,8 @@
 	object_class->get_header = mime_part_get_header;
 	object_class->get_headers = mime_part_get_headers;
 	object_class->write_to_stream = mime_part_write_to_stream;
+	
+	klass->set_content_object = set_content_object;
 }
 
 static void
@@ -426,8 +431,8 @@
 
 /**
  * g_mime_part_new_with_type:
- * @type: content-type
- * @subtype: content-subtype
+ * @type: content-type string
+ * @subtype: content-subtype string
  *
  * Creates a new MIME Part with a sepcified type.
  *
@@ -451,7 +456,7 @@
 
 /**
  * g_mime_part_set_content_description:
- * @mime_part: Mime part
+ * @mime_part: a #GMimePart object
  * @description: content description
  *
  * Set the content description for the specified mime part.
@@ -461,9 +466,10 @@
 {
 	g_return_if_fail (GMIME_IS_PART (mime_part));
 	
-	if (mime_part->content_description)
-		g_free (mime_part->content_description);
+	if (mime_part->content_description == description)
+		return;
 	
+	g_free (mime_part->content_description);
 	mime_part->content_description = g_strdup (description);
 	g_mime_header_list_set (GMIME_OBJECT (mime_part)->headers, "Content-Description", description);
 }
@@ -471,7 +477,7 @@
 
 /**
  * g_mime_part_get_content_description:
- * @mime_part: Mime part
+ * @mime_part: a #GMimePart object
  *
  * Gets the value of the Content-Description for the specified mime
  * part if it exists or %NULL otherwise.
@@ -489,7 +495,7 @@
 
 /**
  * g_mime_part_set_content_id:
- * @mime_part: Mime part
+ * @mime_part: a #GMimePart object
  * @content_id: content id
  *
  * Set the content id for the specified mime part.
@@ -505,7 +511,7 @@
 
 /**
  * g_mime_part_get_content_id:
- * @mime_part: Mime part
+ * @mime_part: a #GMimePart object
  *
  * Gets the content-id of the specified mime part if it exists, or
  * %NULL otherwise.
@@ -523,7 +529,7 @@
 
 /**
  * g_mime_part_set_content_md5:
- * @mime_part: Mime part
+ * @mime_part: a #GMimePart object
  * @content_md5: content md5 or %NULL to generate the md5 digest.
  *
  * Set the content md5 for the specified mime part.
@@ -542,8 +548,7 @@
 	
 	g_return_if_fail (GMIME_IS_PART (mime_part));
 	
-	if (mime_part->content_md5)
-		g_free (mime_part->content_md5);
+	g_free (mime_part->content_md5);
 	
 	if (!content_md5) {
 		/* compute a md5sum */
@@ -585,7 +590,7 @@
 
 /**
  * g_mime_part_verify_content_md5:
- * @mime_part: Mime part
+ * @mime_part: a #GMimePart object
  *
  * Verify the content md5 for the specified mime part.
  *
@@ -644,7 +649,7 @@
 
 /**
  * g_mime_part_get_content_md5:
- * @mime_part: Mime part
+ * @mime_part: a #GMimePart object
  *
  * Gets the md5sum contained in the Content-Md5 header of the
  * specified mime part if it exists, or %NULL otherwise.
@@ -672,9 +677,10 @@
 {
 	g_return_if_fail (GMIME_IS_PART (mime_part));
 	
-	if (mime_part->content_location)
-		g_free (mime_part->content_location);
+	if (mime_part->content_location == content_location)
+		return;
 	
+	g_free (mime_part->content_location);
 	mime_part->content_location = g_strdup (content_location);
 	g_mime_header_list_set (GMIME_OBJECT (mime_part)->headers, "Content-Location", content_location);
 }
@@ -700,7 +706,7 @@
 
 /**
  * g_mime_part_set_content_encoding:
- * @mime_part: a #GMimePart
+ * @mime_part: a #GMimePart object
  * @encoding: a #GMimeContentEncoding
  *
  * Set the content encoding for the specified mime part.
@@ -718,7 +724,7 @@
 
 /**
  * g_mime_part_get_content_encoding:
- * @mime_part: a #GMimePart
+ * @mime_part: a #GMimePart object
  *
  * Gets the content encoding of the mime part.
  *
@@ -735,7 +741,7 @@
 
 /**
  * g_mime_part_set_filename:
- * @mime_part: Mime part
+ * @mime_part: a #GMimePart object
  * @filename: the filename of the Mime Part's content
  *
  * Sets the "filename" parameter on the Content-Disposition and also sets the
@@ -755,7 +761,7 @@
 
 /**
  * g_mime_part_get_filename:
- * @mime_part: Mime part
+ * @mime_part: a #GMimePart object
  *
  * Gets the filename of the specificed mime part, or %NULL if the mime
  * part does not have the filename or name parameter set.
@@ -780,10 +786,20 @@
 }
 
 
+static void
+set_content_object (GMimePart *mime_part, GMimeDataWrapper *content)
+{
+	if (mime_part->content)
+		g_object_unref (mime_part->content);
+	
+	mime_part->content = content;
+	g_object_ref (content);
+}
+
 /**
  * g_mime_part_set_content_object:
- * @mime_part: MIME Part
- * @content: content object
+ * @mime_part: a #GMimePart object
+ * @content: a #GMimeDataWrapper content object
  *
  * Sets the content object on the mime part.
  **/
@@ -792,19 +808,16 @@
 {
 	g_return_if_fail (GMIME_IS_PART (mime_part));
 	
-	if (content)
-		g_object_ref (content);
-	
-	if (mime_part->content)
-		g_object_unref (mime_part->content);
+	if (mime_part->content == content)
+		return;
 	
-	mime_part->content = content;
+	GMIME_PART_GET_CLASS (mime_part)->set_content_object (mime_part, content);
 }
 
 
 /**
  * g_mime_part_get_content_object:
- * @mime_part: MIME part object
+ * @mime_part: a #GMimePart object
  *
  * Gets the internal data-wrapper of the specified mime part, or %NULL
  * on error.

Modified: trunk/gmime/gmime-part.h
==============================================================================
--- trunk/gmime/gmime-part.h	(original)
+++ trunk/gmime/gmime-part.h	Sat Sep  6 14:39:15 2008
@@ -50,7 +50,7 @@
  * @content_md5: Content-MD5 string
  * @content: a #GMimeDataWrapper representing the MIME part's content
  *
- * Base leaf-node MIME part object.
+ * A leaf-node MIME part object.
  **/
 struct _GMimePart {
 	GMimeObject parent_object;
@@ -66,6 +66,7 @@
 struct _GMimePartClass {
 	GMimeObjectClass parent_class;
 	
+	void (* set_content_object) (GMimePart *mime_part, GMimeDataWrapper *content);
 };
 
 



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