[evolution-patches] 65058, take 2, content-location patch




Another stupidly big patch that ruined my day ... since the current code works in most practical cases maybe it should only go into 2.1.

It makes content-location 'work better', it passes all the tests jeff has, test 18 still fails, but the mail is just broken (the img tags refer to a remote location not the internal ones).  All my spam still seems to render ok (woohoo).

I couldn't guarantee that it doesn't add new bugs, but as far as i can tell it should fix more than it makes.

--
Michael Zucchi <notzed ximian com>
"born to die, live to work, it's all downhill from here"
Novell's Evolution and Free Software Developer
Index: camel/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/camel/ChangeLog,v
retrieving revision 1.2251.2.4
diff -u -3 -r1.2251.2.4 ChangeLog
--- camel/ChangeLog	22 Sep 2004 01:11:39 -0000	1.2251.2.4
+++ camel/ChangeLog	22 Sep 2004 08:56:45 -0000
@@ -1,5 +1,8 @@
 2004-09-22  Not Zed  <NotZed Ximian com>
 
+	* camel-url.c (camel_url_new_with_base): don't try to dereference
+	base->path if it is NULL.
+
 	* camel-folder-summary.c (camel_folder_summary_decode_token):
 	handle a zero-length token read rather than failing.
 
Index: camel/camel-url.c
===================================================================
RCS file: /cvs/gnome/evolution/camel/camel-url.c,v
retrieving revision 1.40
diff -u -3 -r1.40 camel-url.c
--- camel/camel-url.c	11 Jun 2004 08:28:41 -0000	1.40
+++ camel/camel-url.c	22 Sep 2004 08:56:48 -0000
@@ -210,8 +210,8 @@
 		} else if (*url->path != '/') {
 			char *newpath, *last, *p, *q;
 
-			last = strrchr (base->path, '/');
-			if (last) {
+			if (base->path
+			    && (last = strrchr (base->path, '/'))) {
 				newpath = g_strdup_printf ("%.*s/%s",
 							   last - base->path,
 							   base->path,
Index: mail/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/mail/ChangeLog,v
retrieving revision 1.3444.2.9
diff -u -3 -r1.3444.2.9 ChangeLog
--- mail/ChangeLog	22 Sep 2004 01:31:16 -0000	1.3444.2.9
+++ mail/ChangeLog	22 Sep 2004 08:56:55 -0000
@@ -1,3 +1,49 @@
+2004-09-22  Not Zed  <NotZed Ximian com>
+
+	** See bug #65058 (more complete fix).
+
+	* em-format-html.c (efh_format_do): fixed for changed data
+	structures.
+	(efh_multipart_related): clean up some code with new apis
+
+	* em-format.h (EMFormatPURI): Added a parent pointer to the tree
+	structure, and made the uri mutli-valued for alternatives.
+
+	* em-format-html.h (EMFormatHTMLJob): Removed the pending uri
+	level and base url, the puri has pointers to this info now.
+
+	* em-format-html.c (emfh_getpuri): close the stream to indicate
+	successful output, and handle the pending uri level for the job
+	based on the pending uri now.
+
+	* em-format.c (em_format_add_puri): also check the filename as a
+	possible content-location fallback, and don't use an absolute uri
+	as the content-id for made-up parts.  We also now have a list of
+	uri's rather than a single one.
+	(em_format_pull_level): reset the part-id string as well as the
+	level pointer.
+	(dump_visible_rec, dump_visible): some messy debug stuff.
+	(em_format_find_visible_puri): make this search below the current
+	point as well as above it.
+	(emf_find_puri_rec, emf_find_puri): helpers for above since we
+	need to search more uris now.
+	(emf_clear_puri_node): free the multiple uris and the base url for
+	this level.
+	(emf_multipart_mixed): push a wrapper level incase the
+	multipart/mixed has a content-location value.
+	(emf_multipart_alternative): ditto for multipart/alternative.
+	(emf_multipart_related): use the new push_level stuff to kill some
+	code.
+
+	* em-format.h: removed base from emformat, put it in the puri
+	level tree instead.
+
+	* em-format.c (em_format_push_level): add uri and partid arguments
+	to push level of.  We now keep track of the base-url for each
+	level explictly too.
+
+	* em-format-html.c (emfh_gethttp): d() out debug printf.
+
 2004-09-03  Not Zed  <NotZed Ximian com>
 
 	** See bug #65058.
Index: mail/em-format-html.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-html.c,v
retrieving revision 1.63.4.1
diff -u -3 -r1.63.4.1 em-format-html.c
--- mail/em-format-html.c	22 Sep 2004 01:31:16 -0000	1.63.4.1
+++ mail/em-format-html.c	22 Sep 2004 08:56:59 -0000
@@ -410,11 +410,8 @@
 	struct _EMFormatHTMLJob *job = g_malloc0(sizeof(*job));
 
 	job->format = emfh;
-	job->puri_level = ((EMFormat *)emfh)->pending_uri_level;
 	job->callback = callback;
 	job->u.data = data;
-	if (((EMFormat *)emfh)->base)
-		job->base = camel_url_copy(((EMFormat *)emfh)->base);
 
 	return job;
 }
@@ -432,8 +429,16 @@
 static void emfh_getpuri(struct _EMFormatHTMLJob *job, int cancelled)
 {
 	d(printf(" running getpuri task\n"));
-	if (!cancelled)
+	if (!cancelled) {
+		struct _EMFormatPURITree *puri_level;
+		
+		puri_level = ((EMFormat *)job->format)->pending_uri_level;
+		((EMFormat *)job->format)->pending_uri_level = job->u.puri->level;
+
 		job->u.puri->func((EMFormat *)job->format, job->stream, job->u.puri);
+		camel_stream_close(job->stream);
+		((EMFormat *)job->format)->pending_uri_level = puri_level;
+	}
 }
 
 static void emfh_gethttp(struct _EMFormatHTMLJob *job, int cancelled)
@@ -455,7 +460,7 @@
 	if (instream == NULL) {
 		char *proxy;
 
-		printf(" load http %d now=%d\n", job->format->load_http, job->format->load_http_now);
+		d(printf(" load http %d now=%d\n", job->format->load_http, job->format->load_http_now));
 
 		if (!(job->format->load_http_now
 		      || job->format->load_http == MAIL_CONFIG_HTTP_ALWAYS
@@ -824,8 +829,9 @@
 	}
 
 	puri = em_format_add_puri((EMFormat *)efh, sizeof(EMFormatPURI), NULL, part, efh_write_text_html);
-	location = puri->uri?puri->uri:puri->cid;
+	location = puri->uris&&puri->uris[0]?puri->uris[0]:puri->cid;
 	d(printf("adding iframe, location %s\n", location));
+
 	camel_stream_printf(stream,
 			    "<iframe src=\"%s\" frameborder=0 scrolling=no>could not get %s</iframe>\n"
 			    "</td></tr></table>\n"
@@ -973,12 +979,12 @@
 	d(printf(" running multipart/related check task\n"));
 	oldpartid = g_strdup(((EMFormat *)job->format)->part_id->str);
 
-	ptree = job->puri_level;
+	ptree = (struct _EMFormatPURITree *)job->u.data;
 	puri = (EMFormatPURI *)ptree->uri_list.head;
 	purin = puri->next;
 	while (purin) {
 		if (puri->use_count == 0) {
-			d(printf("part '%s' '%s' used '%d'\n", puri->uri?puri->uri:"", puri->cid, puri->use_count));
+			d(printf("part '%s' '%s' used '%d'\n", puri->uris?puri->uris[0]:"", puri->cid, puri->use_count));
 			if (puri->func == emfh_write_related) {
 				g_string_printf(((EMFormat *)job->format)->part_id, puri->part_id);
 				em_format_part((EMFormat *)job->format, (CamelStream *)job->stream, puri->part);
@@ -1000,9 +1006,8 @@
 	CamelMultipart *mp = (CamelMultipart *)camel_medium_get_content_object((CamelMedium *)part);
 	CamelMimePart *body_part, *display_part = NULL;
 	CamelContentType *content_type;
-	const char *location, *start;
+	const char *start;
 	int i, nparts, partidlen, displayid = 0;
-	CamelURL *base_save = NULL;
 	EMFormatPURI *puri;
 	struct _EMFormatHTMLJob *job;
 
@@ -1041,45 +1046,32 @@
 		return;
 	}
 	
-	/* stack of present location and pending uri's */
-	location = camel_mime_part_get_content_location(part);
-	if (location) {
-		d(printf("setting content location %s\n", location));
-		base_save = emf->base;
-		emf->base = camel_url_new(location, NULL);
-	}
-	em_format_push_level(emf);
-
+	em_format_push_level(emf, camel_mime_part_get_content_location(part), ".related");
 	partidlen = emf->part_id->len;
 
 	/* queue up the parts for possible inclusion */
 	for (i = 0; i < nparts; i++) {
 		body_part = camel_multipart_get_part(mp, i);
 		if (body_part != display_part) {
-			g_string_append_printf(emf->part_id, "related.%d", i);
+			g_string_append_printf(emf->part_id, ".%d", i);
 			puri = em_format_add_puri(emf, sizeof(EMFormatPURI), NULL, body_part, emfh_write_related);
 			g_string_truncate(emf->part_id, partidlen);
-			d(printf(" part '%s' '%s' added\n", puri->uri?puri->uri:"", puri->cid));
+			d(printf(" part '%s' '%s' added\n", puri->uris?puri->uris[0]:"", puri->cid));
 		}
 	}
 	
-	g_string_append_printf(emf->part_id, "related.%d", displayid);
+	g_string_append_printf(emf->part_id, ".%d", displayid);
 	em_format_part(emf, stream, display_part);
 	g_string_truncate(emf->part_id, partidlen);
 	camel_stream_flush(stream);
 
 	/* queue a job to check for un-referenced parts to add as attachments */
-	job = em_format_html_job_new((EMFormatHTML *)emf, emfh_multipart_related_check, NULL);
+	job = em_format_html_job_new((EMFormatHTML *)emf, emfh_multipart_related_check, emf->pending_uri_level);
 	job->stream = stream;
 	camel_object_ref(stream);
 	em_format_html_job_queue((EMFormatHTML *)emf, job);
 
 	em_format_pull_level(emf);
-	
-	if (location) {
-		camel_url_free(emf->base);
-		emf->base = base_save;
-	}
 }
 
 static void
@@ -1167,9 +1159,7 @@
 {
 	struct _format_msg *m = (struct _format_msg *)mm;
 	struct _EMFormatHTMLJob *job;
-	struct _EMFormatPURITree *puri_level;
 	int cancelled = FALSE;
-	CamelURL *base;
 
 	if (m->format->html == NULL) 
 		return;
@@ -1195,9 +1185,6 @@
 	camel_object_unref(m->estream);
 	m->estream = NULL;
 
-	puri_level = ((EMFormat *)m->format)->pending_uri_level;
-	base = ((EMFormat *)m->format)->base;
-
 	/* now dispatch any added tasks ... */
 	g_mutex_lock(m->format->priv->lock);
 	while ((job = (struct _EMFormatHTMLJob *)e_dlist_remhead(&m->format->priv->pending_jobs))) {
@@ -1212,24 +1199,16 @@
 			cancelled = camel_operation_cancel_check(NULL);
 
 		/* call jobs even if cancelled, so they can clean up resources */
-		((EMFormat *)m->format)->pending_uri_level = job->puri_level;
-		if (job->base)
-			((EMFormat *)m->format)->base = job->base;
 		job->callback(job, cancelled);
-		((EMFormat *)m->format)->base = base;
 
 		/* clean up the job */
 		camel_object_unref(job->stream);
-		if (job->base)
-			camel_url_free(job->base);
 		g_free(job);
 
 		g_mutex_lock(m->format->priv->lock);
 	}
 	g_mutex_unlock(m->format->priv->lock);
 	d(printf("out of jobs, done\n"));
-
-	((EMFormat *)m->format)->pending_uri_level = puri_level;
 }
 
 static void efh_format_done(struct _mail_msg *mm)
Index: mail/em-format-html.h
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format-html.h,v
retrieving revision 1.14
diff -u -3 -r1.14 em-format-html.h
--- mail/em-format-html.h	18 May 2004 07:48:19 -0000	1.14
+++ mail/em-format-html.h	22 Sep 2004 08:56:59 -0000
@@ -55,17 +55,11 @@
 	EMFormatHTML *format;
 	struct _CamelStream *stream;
 
-	/* We need to track the state of the visibility tree at
-	   the point this uri was generated */
-	struct _EMFormatPURITree *puri_level;
-	struct _CamelURL *base;
-
 	void (*callback)(struct _EMFormatHTMLJob *job, int cancelled);
 	union {
 		char *uri;
 		struct _CamelMedium *msg;
 		EMFormatPURI *puri;
-		struct _EMFormatPURITree *puri_level;
 		void *data;
 	} u;
 };
Index: mail/em-format.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format.c,v
retrieving revision 1.38.8.1
diff -u -3 -r1.38.8.1 em-format.c
--- mail/em-format.c	7 Sep 2004 14:22:12 -0000	1.38.8.1
+++ mail/em-format.c	22 Sep 2004 08:57:00 -0000
@@ -327,41 +327,68 @@
 	}
 
 	if (part != NULL && cid == NULL) {
+		CamelURL *url, *base;
+		int uri = 0, i;
+
 		tmp = camel_mime_part_get_content_id(part);
 		if (tmp)
 			puri->cid = g_strdup_printf("cid:%s", tmp);
 		else
-			puri->cid = g_strdup_printf("em-no-cid:%s", emf->part_id->str);
+			puri->cid = g_strdup_printf("%s", emf->part_id->str);
 
 		d(printf("built cid '%s'\n", puri->cid));
 
-		/* not quite same as old behaviour, it also put in the relative uri and a fallback for no parent uri */
-		tmp = camel_mime_part_get_content_location(part);
-		puri->uri = NULL;
-		if (tmp == NULL) {
-			if (emf->base)
-				puri->uri = camel_url_to_string(emf->base, 0);
-		} else {
-			if (strchr(tmp, ':') == NULL && emf->base != NULL) {
-				CamelURL *uri;
-
-				uri = camel_url_new_with_base(emf->base, tmp);
-				puri->uri = camel_url_to_string(uri, 0);
-				camel_url_free(uri);
-			} else {
-				puri->uri = g_strdup(tmp);
+		if (emf->pending_uri_level && emf->pending_uri_level->base)
+			base = emf->pending_uri_level->base;
+		else
+			base = NULL;
+
+		/* we only have 2 possibilities max, this is null terminated */
+		puri->uris = g_malloc0(sizeof(*puri->uris)*3);
+
+		/* 1: try location, 2: try filename */
+		for (i=0;i<2;i++) {
+			if (i == 0)
+				tmp = camel_mime_part_get_content_location(part);
+			else
+				tmp = camel_mime_part_get_filename(part);
+			if (tmp) {
+				if (strchr(tmp, ':') == NULL && base != NULL) {
+					url = camel_url_new_with_base(base, tmp);
+					puri->uris[uri++] = camel_url_to_string(url, 0);
+					camel_url_free(url);
+				} else {
+					puri->uris[uri++] = g_strdup(tmp);
+				}
 			}
 		}
+
+		/* last chance */
+		if (uri == 0 && base)
+			puri->uris[uri++] = camel_url_to_string(base, 0);
+
+		if (uri == 0) {
+			g_free(puri->uris);
+			puri->uris = NULL;
+		}
 	}
 
 	g_assert(puri->cid != NULL);
 	g_assert(emf->pending_uri_level != NULL);
 	g_assert(emf->pending_uri_table != NULL);
 
+	d(printf("adding puri cid:'%s' uri[0]:'%s''\n", puri->cid, puri->uris?puri->uris[0]:"<unset>"));
+
+	puri->level = emf->pending_uri_level;
 	e_dlist_addtail(&emf->pending_uri_level->uri_list, (EDListNode *)puri);
 
-	if (puri->uri)
-		g_hash_table_insert(emf->pending_uri_table, puri->uri, puri);
+	if (puri->uris) {
+		int i;
+
+		for (i=0;puri->uris[i];i++)
+			g_hash_table_insert(emf->pending_uri_table, puri->uris[i], puri);
+	}
+
 	g_hash_table_insert(emf->pending_uri_table, puri->cid, puri);
 
 	return puri;
@@ -370,27 +397,44 @@
 /**
  * em_format_push_level:
  * @emf: 
+ * @uri: absolute or relative uri of this part.  May be null.
+ * @partid: part-id prefix of this part. May be null.
  * 
  * This is used to build a heirarchy of visible PURI objects based on
  * the structure of the message.  Used by multipart/alternative formatter.
  *
- * FIXME: This could probably also take a uri so it can automaticall update
- * the base location.
+ * It also updates the base uri and partid string
+ * appropriately.
  **/
 void
-em_format_push_level(EMFormat *emf)
+em_format_push_level(EMFormat *emf, const char *uri, const char *partid)
 {
-	struct _EMFormatPURITree *purilist;
+	struct _EMFormatPURITree *purilist, *parent;
 
-	d(printf("em_format_push_level\n"));
+	parent = emf->pending_uri_level;
+
+	d(printf("em_format_push_level '%s' '%s'\n", uri?uri:"<none>", partid?partid:"<none>"));
 	purilist = g_malloc0(sizeof(*purilist));
 	e_dlist_init(&purilist->children);
 	e_dlist_init(&purilist->uri_list);
-	purilist->parent = emf->pending_uri_level;
-	if (emf->pending_uri_tree == NULL) {
+	purilist->parent = parent;
+
+	if (uri) {
+		if (parent && parent->base)
+			purilist->base = camel_url_new_with_base(parent->base, uri);
+		else
+			purilist->base = camel_url_new(uri, NULL);
+	} else if (parent && parent->base)
+		purilist->base = camel_url_copy(parent->base);
+
+	purilist->idlen = emf->part_id->len;
+	if (partid)
+		g_string_append(emf->part_id, partid);
+
+	if (parent == NULL) {
 		emf->pending_uri_tree = purilist;
 	} else {
-		e_dlist_addtail(&emf->pending_uri_level->children, (EDListNode *)purilist);
+		e_dlist_addtail(&parent->children, (EDListNode *)purilist);
 	}
 	emf->pending_uri_level = purilist;
 }
@@ -399,14 +443,129 @@
  * em_format_pull_level:
  * @emf: 
  * 
- * Drop a level of visibility back to the parent.  Note that
- * no PURI values are actually freed.
+ * Drop a level of visibility back to the parent.  Note that no PURI
+ * values are actually freed.  This resets the partid string and
+ * emf->base uri to what they were before.
  **/
 void
 em_format_pull_level(EMFormat *emf)
 {
+	struct _EMFormatPURITree *ptree;
+
 	d(printf("em_format_pull_level\n"));
-	emf->pending_uri_level = emf->pending_uri_level->parent;
+
+	ptree = emf->pending_uri_level;
+	g_string_truncate(emf->part_id, ptree->idlen);
+	emf->pending_uri_level = ptree->parent;
+}
+
+#if d(!)0
+static void
+dump_visible_rec(struct _EMFormatPURITree *root, struct _EMFormatPURITree *here, int level)
+{
+	char *s;
+	EMFormatPURI *pw;
+	struct _EMFormatPURITree *child;
+
+	s = alloca(level+2);
+	memset(s, ' ', level+1);
+	s[level+1] = 0;
+
+	while (root->next) {
+		if (root == here)
+			s[0] = '*';
+		else
+			s[0] = ' ';
+
+		pw = (EMFormatPURI *)root->uri_list.head;
+		while (pw->next) {
+			printf("%spw->uri[0] = '%s' pw->cid = '%s\n", s, pw->uris?pw->uris[0]:"", pw->cid);
+			pw = pw->next;
+		}
+		
+		child = root->children.head;
+		while (child->next) {
+			dump_visible_rec(child, here, level+1);
+			child = child->next;
+		}
+
+		root = root->next;
+	}
+}
+
+static void
+dump_visible(struct _EMFormatPURITree *root, struct _EMFormatPURITree *here, int level)
+{
+	char *s;
+	EMFormatPURI *pw;
+	struct _EMFormatPURITree *child;
+
+	s = alloca(level+2);
+	memset(s, ' ', level+1);
+	s[level+1] = 0;
+
+	if (root == here)
+		s[0] = '*';
+
+	printf("tree:<\n");
+	pw = (EMFormatPURI *)root->uri_list.head;
+	while (pw->next) {
+		printf("%spw->uri[0] = '%s' pw->cid = '%s\n", s, pw->uris?pw->uris[0]:"", pw->cid);
+		pw = pw->next;
+	}
+	child = root->children.head;
+	while (child->next) {
+		dump_visible_rec(child, here, level+1);
+		child = child->next;
+	}
+	root = root->next;
+	printf(">\n");
+}
+#endif
+
+static EMFormatPURI *
+emf_find_puri(EMFormatPURI *pw, const char *uri)
+{
+	while (pw->next) {
+		if (pw->uris) {
+			int i;
+
+			for (i=0;pw->uris[i];i++) {
+				d(printf(" pw->uri[%d] = '%s'\n", i, pw->uris[i]));
+				if (!strcmp(pw->uris[i], uri)) {
+					d(printf("match!\n"));
+					return pw;
+				}
+			}
+		}
+
+		d(printf(" pw->cid = '%s'\n", pw->cid));
+		if (!strcmp(pw->cid, uri)) {
+			d(printf("match!\n"));
+			return pw;
+		}
+		pw = pw->next;
+	}
+
+	return NULL;
+}
+
+static EMFormatPURI *
+emf_find_puri_rec(struct _EMFormatPURITree *ptree, const char *uri)
+{
+	while (ptree->next) {
+		EMFormatPURI *pw;
+
+		pw = emf_find_puri((EMFormatPURI *)ptree->uri_list.head, uri);
+		if (pw != NULL)
+			return pw;
+		pw = emf_find_puri_rec((struct _EMFormatPURITree *)ptree->children.head, uri);
+		if (pw != NULL)
+			return pw;
+		ptree = ptree->next;
+	}
+
+	return NULL;
 }
 
 /**
@@ -426,19 +585,24 @@
 	struct _EMFormatPURITree *ptree;
 
 	d(printf("checking for visible uri '%s'\n", uri));
+	if (emf->pending_uri_tree)
+		d(dump_visible(emf->pending_uri_tree, emf->pending_uri_level, 0));
 
 	ptree = emf->pending_uri_level;
 	while (ptree) {
-		pw = (EMFormatPURI *)ptree->uri_list.head;
-		while (pw->next) {
-			d(printf(" pw->uri = '%s' pw->cid = '%s\n", pw->uri?pw->uri:"", pw->cid));
-			if ((pw->uri && !strcmp(pw->uri, uri)) || !strcmp(pw->cid, uri))
-				return pw;
-			pw = pw->next;
-		}
+		/* first at this level */
+		pw = emf_find_puri((EMFormatPURI *)ptree->uri_list.head, uri);
+		if (pw != NULL)
+			return pw;
+		/* and then all children recursively */
+		pw = emf_find_puri_rec((struct _EMFormatPURITree *)ptree->children.head, uri);
+		if (pw != NULL)
+			return pw;
 		ptree = ptree->parent;
 	}
 
+	d(printf("no match?\n"));
+
 	return NULL;
 }
 
@@ -468,7 +632,13 @@
 		pw = (EMFormatPURI *)node->uri_list.head;
 		pn = pw->next;
 		while (pn) {
-			g_free(pw->uri);
+			if (pw->uris) {
+				int i;
+
+				for (i=0;pw->uris[i];i++)
+					g_free(pw->uris[i]);
+				g_free(pw->uris);
+			}
 			g_free(pw->cid);
 			g_free(pw->part_id);
 			if (pw->part)
@@ -487,6 +657,8 @@
 		cn = cw->next;
 		while (cn) {
 			emf_clear_puri_node(cw);
+			if (cw->base)
+				camel_url_free(cw->base);
 			cw = cn;
 			cn = cn->next;
 		}
@@ -514,7 +686,7 @@
 		emf->pending_uri_tree = NULL;
 	}
 	emf->pending_uri_table = g_hash_table_new(g_str_hash, g_str_equal);
-	em_format_push_level(emf);
+	em_format_push_level(emf, NULL, NULL);
 }
 
 /* use mime_type == NULL  to force showing as application/octet-stream */
@@ -1144,14 +1316,18 @@
 		return;
 	}
 
+	em_format_push_level(emf, camel_mime_part_get_content_location(part), ".mixed");
 	len = emf->part_id->len;
+
 	nparts = camel_multipart_get_number(mp);	
 	for (i = 0; i < nparts; i++) {
 		part = camel_multipart_get_part(mp, i);
-		g_string_append_printf(emf->part_id, ".mixed.%d", i);
+		g_string_append_printf(emf->part_id, ".%d", i);
 		em_format_part(emf, stream, part);
 		g_string_truncate(emf->part_id, len);
 	}
+
+	em_format_pull_level(emf);
 }
 
 /* RFC 1740 */
@@ -1189,11 +1365,10 @@
 	}
 
 	if (best) {
-		int len = emf->part_id->len;
-
-		g_string_append_printf(emf->part_id, ".alternative.%d", bestid);
+		em_format_push_level(emf, camel_mime_part_get_content_location(part), ".alternative");
+		g_string_append_printf(emf->part_id, ".%d", bestid);
 		em_format_part(emf, stream, best);
-		g_string_truncate(emf->part_id, len);
+		em_format_pull_level(emf);
 	} else
 		emf_multipart_mixed(emf, stream, part, info);
 }
@@ -1262,10 +1437,8 @@
 	CamelMultipart *mp = (CamelMultipart *)camel_medium_get_content_object((CamelMedium *)part);
 	CamelMimePart *body_part, *display_part = NULL;
 	CamelContentType *content_type;
-	const char *location, *start;
+	const char *start;
 	int i, nparts, partidlen, displayid = 0;
-	char *oldpartid;
-	CamelURL *base_save = NULL;
 	struct _EMFormatPURITree *ptree;
 	EMFormatPURI *puri, *purin;
 
@@ -1304,17 +1477,8 @@
 		emf_multipart_mixed(emf, stream, part, info);
 		return;
 	}
-	
-	/* stack of present location and pending uri's */
-	location = camel_mime_part_get_content_location(part);
-	if (location) {
-		d(printf("setting content location %s\n", location));
-		base_save = emf->base;
-		emf->base = camel_url_new(location, NULL);
-	}
-	em_format_push_level(emf);
 
-	oldpartid = g_strdup(emf->part_id->str);
+	em_format_push_level(emf, camel_mime_part_get_content_location(part), ".related");
 	partidlen = emf->part_id->len;
 
 	/* queue up the parts for possible inclusion */
@@ -1322,14 +1486,14 @@
 		body_part = camel_multipart_get_part(mp, i);
 		if (body_part != display_part) {
 			/* set the partid since add_puri uses it */
-			g_string_append_printf(emf->part_id, ".related.%d", i);
+			g_string_append_printf(emf->part_id, ".%d", i);
 			puri = em_format_add_puri(emf, sizeof(EMFormatPURI), NULL, body_part, emf_write_related);
 			g_string_truncate(emf->part_id, partidlen);
-			d(printf(" part '%s' '%s' added\n", puri->uri?puri->uri:"", puri->cid));
+			d(printf(" part '%s' '%s' added\n", puri->uris?puri->uris[0]:"", puri->cid));
 		}
 	}
 	
-	g_string_append_printf(emf->part_id, ".related.%d", displayid);
+	g_string_append_printf(emf->part_id, ".%d", displayid);
 	em_format_part(emf, stream, display_part);
 	g_string_truncate(emf->part_id, partidlen);
 	camel_stream_flush(stream);
@@ -1339,26 +1503,18 @@
 	purin = puri->next;
 	while (purin) {
 		if (puri->use_count == 0) {
-			d(printf("part '%s' '%s' used '%d'\n", puri->uri?puri->uri:"", puri->cid, puri->use_count));
+			d(printf("part '%s' '%s' used '%d'\n", puri->uris?puri->uris[0]:"", puri->cid, puri->use_count));
 			if (puri->func == emf_write_related) {
 				g_string_printf(emf->part_id, "%s", puri->part_id);
 				em_format_part(emf, stream, puri->part);
 			} else
-				printf("unreferenced uri generated by format code: %s\n", puri->uri?puri->uri:puri->cid);
+				printf("unreferenced uri generated by format code: %s\n", puri->uris?puri->uris[0]:puri->cid);
 		}
 		puri = purin;
 		purin = purin->next;
 	}
 
-	g_string_printf(emf->part_id, "%s", oldpartid);
-	g_free(oldpartid);
-
 	em_format_pull_level(emf);
-	
-	if (location) {
-		camel_url_free(emf->base);
-		emf->base = base_save;
-	}
 }
 
 static void
Index: mail/em-format.h
===================================================================
RCS file: /cvs/gnome/evolution/mail/em-format.h,v
retrieving revision 1.12
diff -u -3 -r1.12 em-format.h
--- mail/em-format.h	10 Jul 2004 01:31:04 -0000	1.12
+++ mail/em-format.h	22 Sep 2004 08:57:00 -0000
@@ -74,13 +74,15 @@
 
 	struct _EMFormat *format;
 
-	char *uri;		/* will be the location of the part, may be empty */
+	char **uris;		/* posible location of the part, starting with most likely, null terminated array */
 	char *cid;		/* will always be set, a fake one created if needed */
 	char *part_id;		/* will always be set, emf->part_id->str for this part */
 
 	EMFormatPURIFunc func;
 	struct _CamelMimePart *part;
 
+	struct _EMFormatPURITree *level;
+
 	unsigned int use_count;	/* used by multipart/related to see if it was accessed */
 };
 
@@ -90,6 +92,9 @@
 
 	EDList uri_list;
 	EDList children;
+
+	int idlen;		/* old part-id len */
+	struct _CamelURL *base;	/* url base of saved part */
 };
 
 struct _EMFormatHeader {
@@ -117,7 +122,6 @@
 	EDList header_list;	/* if empty, then all */
 
 	struct _CamelSession *session; /* session, used for authentication when required */
-	struct _CamelURL *base;		/* current location (base url) */
 
 	const char *snoop_mime_type; /* if we snooped an application/octet-stream type, what we snooped */
 
@@ -209,7 +213,7 @@
 EMFormatPURI *em_format_find_visible_puri(EMFormat *emf, const char *uri);
 EMFormatPURI *em_format_find_puri(EMFormat *emf, const char *uri);
 void em_format_clear_puri_tree(EMFormat *emf);
-void em_format_push_level(EMFormat *emf);
+void em_format_push_level(EMFormat *emf, const char *uri, const char *partid);
 void em_format_pull_level(EMFormat *emf);
 
 /* clones inline state/view and format, or use to redraw */


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