Re: [evolution-patches] Exchange connector patch for attachments



Found some bugs in the previous (exchange) patch which i have fixed in this new one. Please review.

On Fri, 2005-03-11 at 12:34 +0530, Sarfraaz Ahmed wrote:
Hi,

This patch includes changes to e-d-s and connector. I have attached separate patches for both.

Thanks
-- Sarfraaz

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/ChangeLog,v
retrieving revision 1.432.2.1
diff -u -p -u -r1.432.2.1 ChangeLog
--- ChangeLog	8 Mar 2005 02:48:31 -0000	1.432.2.1
+++ ChangeLog	11 Mar 2005 07:00:36 -0000
@@ -1,3 +1,8 @@
+2005-03-11  Sarfraaz Ahmed <asarfraaz novell com>
+
+	* libecal/e-cal.c : Set the local_attachment_store for exchange
+	* libecal/e-cal-component.c : Dont unref the attach
+
 2005-03-06  Rodrigo Moya <rodrigo novell com>
 
 	Fixes #72454
Index: libecal/e-cal.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/libecal/e-cal.c,v
retrieving revision 1.94
diff -u -p -u -r1.94 e-cal.c
--- libecal/e-cal.c	9 Feb 2005 00:29:26 -0000	1.94
+++ libecal/e-cal.c	11 Mar 2005 07:00:36 -0000
@@ -1349,6 +1349,10 @@ set_local_attachment_store (ECal *ecal)
 			g_strconcat ("file://", g_get_home_dir (), "/", ".evolution/cache/calendar",
 				     "/", mangled_uri, NULL);
 	}
+	if (g_str_has_prefix (priv->uri, "exchange://")) {
+		priv->local_attachment_store = g_strdup_printf ("file://%s/.evolution/exchange/%s", 
+					g_get_home_dir (), mangled_uri);
+	}
 }
 
 /**
Index: libecal/e-cal-component.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/calendar/libecal/e-cal-component.c,v
retrieving revision 1.13
diff -u -p -u -r1.13 e-cal-component.c
--- libecal/e-cal-component.c	2 Feb 2005 18:44:32 -0000	1.13
+++ libecal/e-cal-component.c	11 Mar 2005 07:00:36 -0000
@@ -1489,7 +1489,6 @@ set_attachment_list (icalcomponent *ical
 
 			icalcomponent_remove_property (icalcomp, attachment->prop);
 			icalproperty_free (attachment->prop);
-			icalattach_unref (attachment->attach);
 			g_free (attachment);
 		}
 
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-exchange/ChangeLog,v
retrieving revision 1.293
diff -u -p -u -r1.293 ChangeLog
--- ChangeLog	10 Mar 2005 17:52:13 -0000	1.293
+++ ChangeLog	11 Mar 2005 14:22:25 -0000
@@ -1,3 +1,26 @@
+2005-03-11  Sarfraaz Ahmed <asarfraaz novell com>
+
+	* calendar/e-cal-backend-exchange-calendar.c (add_ical) : Make sure we
+	check for attachments in subcomponents of a vcalendar as well.
+	(get_attachment) : Moved to e-cal-backend-exchange.c
+	(build_msg) : Moved to e-cal-backend-exchange.c
+	(create_object) : Minor leak fixed.
+	(modify_object_with_href) : Dont loose the attachments while modifying.
+	* calendar/e-cal-backend-exchange-tasks.c (put_body): Handle attachments
+	(get_changed_tasks) : Check for attachments and fetch them from server.
+	(create_task_object) : Check for attachments and send them to server.
+	(modify_task_object) : Similar
+	* calendar/e-cal-backend-exchange.c (load_cache) : Create the local
+	attachment store for the GUI to store exchange attachments
+	(save_attach_file) : Make a local copy of the attachment in the backend
+	(get_attachment) : Extract the attachment from the server object.(Moved
+	from calendar.c)
+	(get_attach_file_contents) : Store the attachment in a file.
+	(build_msg) : Build the mime part to send to the server (Moved from
+	calendar.c)
+	* calendar/e-cal-backend-exchange.h : Export the attachment utility
+	functions.
+
 2005-03-07  Jeffrey Stedfast  <fejj novell com>
 
 	Fixes bug #72889, #72943 and probably others.
Index: calendar/e-cal-backend-exchange.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/calendar/e-cal-backend-exchange.c,v
retrieving revision 1.30
diff -u -p -u -r1.30 e-cal-backend-exchange.c
--- calendar/e-cal-backend-exchange.c	8 Mar 2005 10:29:42 -0000	1.30
+++ calendar/e-cal-backend-exchange.c	11 Mar 2005 14:22:25 -0000
@@ -21,10 +21,21 @@
 #include <config.h>
 #endif
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+
 #include <string.h>
 #include <unistd.h>
 #include <e-util/e-time-utils.h>
 
+#include <libgnomevfs/gnome-vfs-mime-utils.h>
+
+#include <camel/camel-mime-message.h>
+#include <camel/camel-multipart.h>
+#include <camel/camel-stream-mem.h>
+#include <camel/camel-file-utils.h>
+
 #include "e-cal-backend-exchange.h"
 #include "e2k-cal-utils.h"
 #include "e2k-uri.h"
@@ -44,6 +55,7 @@ struct ECalBackendExchangePrivate {
 	GHashTable *objects, *cache_unseen;
 	char *object_cache_file;
 	char *lastmod;
+	char *local_attachment_store;
 	guint save_timeout_id;
 
 	/* Timezones */
@@ -127,11 +139,33 @@ load_cache (ECalBackendExchange *cbex, E
 	struct icaltimetype comp_last_mod, folder_last_mod;
 	icalcomponent_kind kind;
 	icalproperty *prop;
-	char *lastmod;
+	char *lastmod, *mangled_uri, *storage_dir, *end;
+	const char *uristr;
+	int i;
+	struct stat buf;
 
 	cbex->priv->object_cache_file =
 		e_folder_exchange_get_storage_file (cbex->folder, "cache.ics");
 
+	/* Fixme : Try avoiding to do this everytime we come here */
+	uristr = e_cal_backend_get_uri (E_CAL_BACKEND (cbex));
+	mangled_uri = g_strdup (uristr);
+	for (i = 0; i < strlen (mangled_uri); i++) {
+		switch (mangled_uri[i]) {
+		case ':' :
+		case '/' :
+			mangled_uri[i] = '_';
+		}
+	}
+	cbex->priv->local_attachment_store = g_strdup_printf ("%s/.evolution/exchange/%s", g_get_home_dir (), mangled_uri);
+	end = strrchr (cbex->priv->object_cache_file, '/');
+	storage_dir = g_strndup (cbex->priv->object_cache_file, end - cbex->priv->object_cache_file);
+	if (lstat(cbex->priv->local_attachment_store , &buf) < 0) {
+		symlink (storage_dir, cbex->priv->local_attachment_store);
+	}
+	g_free (storage_dir);
+	g_free (mangled_uri);
+
 	vcalcomp = e_cal_util_parse_ics_file (cbex->priv->object_cache_file);
 	if (!vcalcomp)
 		return;
@@ -263,6 +297,7 @@ open_calendar (ECalBackendSync *backend,
 	d(printf("ecbe_open_calendar(%p, %p, %sonly if exists, user=%s, pass=%s)\n", backend, cal, only_if_exists?"":"not ", username?username:"(null)", password?password:"(null)"));
 
 	uristr = e_cal_backend_get_uri (E_CAL_BACKEND (backend));
+
 	if (cbex->priv->mode == CAL_MODE_LOCAL) {
 		ESource *source;
 		const char *display_contents = NULL;
@@ -1244,6 +1279,229 @@ e_cal_backend_exchange_compute_changes_f
 		e_xmlhash_remove (cbedata->ehash, key);
 		g_object_unref (comp);	
 	}
+}
+
+/* Attachments */
+static char *
+save_attach_file (const char *dest_file, char *file_contents, int len)
+{
+	char *dest_url = NULL;
+	int fd;
+
+	d(printf ("dest_file is :%s\n", dest_file));
+
+	/* Write it to our local exchange store in .evolution */
+	fd = open (dest_file, O_RDWR | O_CREAT | O_TRUNC, 0600);
+	if (fd < 0) {
+		d(printf ("open of destination file for attachments failed\n"));
+		goto end;
+	}
+	
+	if (camel_write (fd, file_contents, len) < 0) {
+		d(printf ("camel write to attach file failed\n"));
+		goto end;
+	}
+	/* FIXME : Add a ATTACH:CID:someidentifier here */
+	dest_url = g_strdup_printf ("file://%s", dest_file);
+
+end :
+	close (fd);
+	return dest_url;
+}
+
+GSList * 
+get_attachment (ECalBackendExchange *cbex, const char *uid, 
+			const char *body, int len)
+{
+	CamelStream *stream;
+	CamelMimeMessage *msg;
+	CamelDataWrapper *msg_content, *content = NULL;
+	CamelMultipart *multipart;
+	CamelMimePart *part;
+	const char *filename = NULL;
+	char *attach_file_url, *attach_file;
+	int i;
+	GSList *list = NULL;
+	unsigned char *attach_data;
+
+	stream = camel_stream_mem_new_with_buffer (body, len);
+	msg = camel_mime_message_new ();
+	camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream);
+	camel_object_unref (stream);
+
+	msg_content = camel_medium_get_content_object (CAMEL_MEDIUM (msg));
+	if (msg_content && CAMEL_IS_MULTIPART (msg_content)) {
+		multipart = (CamelMultipart *)msg_content;
+	
+		for (i = 0; i < (int)camel_multipart_get_number (multipart); i++) {
+			part = camel_multipart_get_part (multipart, i);
+			filename = camel_mime_part_get_filename (part);
+			if (filename) {
+				CamelStreamMem *stream_mem;
+
+				content = camel_medium_get_content_object (CAMEL_MEDIUM (part));
+				
+				stream = camel_stream_mem_new ();
+				stream_mem = (CamelStreamMem *)stream;
+			
+				camel_data_wrapper_decode_to_stream (content, stream);
+				attach_data = g_memdup (stream_mem->buffer->data, stream_mem->buffer->len);
+				attach_file = g_strdup_printf ("%s/%s-%s", cbex->priv->local_attachment_store, uid, filename);
+				// Attach
+				attach_file_url = save_attach_file (attach_file, attach_data, stream_mem->buffer->len);
+				g_free (attach_file);
+				d(printf ("attach file name : %s\n", attach_file_url));
+				list = g_slist_append (list, g_strdup (attach_file_url));
+
+				camel_object_unref (stream);
+			}
+		} /* Loop through each multipart */
+	}
+
+	camel_object_unref (msg);
+	return list;
+}
+
+static char *
+get_attach_file_contents (const char *filename)
+{
+	int fd, len = 0;
+	struct stat sb;
+	char *file_contents = NULL;
+
+	fd = open (filename, O_RDONLY);
+	if (fd < 0) {
+		d(printf ("Could not open the attachment file : %s\n", filename));
+		goto end;
+	}
+	if (fstat (fd, &sb) < 0) {
+		d(printf ("fstat of attachment file failed\n"));
+		goto end;
+	}
+	len = sb.st_size;
+
+	if (len > 0) {
+		file_contents = g_malloc0 (len + 1);
+
+		if (camel_read (fd, file_contents, len) < 0) {
+			d(printf ("reading from the attachment file failed\n"));
+			g_free (file_contents);
+			file_contents = NULL;
+			goto end;
+		}
+		file_contents [len] = '\0';
+	}
+
+end :
+	close (fd);
+	return file_contents;
+}
+
+char *
+build_msg ( ECalBackendExchange *cbex, ECalComponent *comp, const char *subject, char **boundary)
+{
+	CamelMimeMessage *msg;
+	CamelStreamMem *content;
+	CamelMimePart *mime_part;
+	CamelDataWrapper *dw, *wrapper;
+	CamelMultipart *multipart;
+	CamelInternetAddress *from;
+	CamelStream *stream;
+	CamelContentType *type;
+	const char *uid;
+	char *buffer = NULL, *cid;
+	char *from_name, *from_email;
+	GSList *attach_list = NULL, *l, *new_attach_list = NULL;
+	char *fname, *file_contents = NULL, *filename, *dest_url, *mime_filename, *attach_file;
+	int len = 0;
+
+	e_cal_backend_exchange_get_from (E_CAL_BACKEND_SYNC (cbex), comp, &from_name, &from_email);
+
+	msg = camel_mime_message_new ();
+
+	multipart = camel_multipart_new ();
+
+	/* Headers */
+	camel_mime_message_set_subject (msg, subject);
+
+	from = camel_internet_address_new ();
+	camel_internet_address_add (from, from_name, from_email);
+	camel_mime_message_set_from (msg, from);
+	camel_object_unref (from);
+
+	e_cal_component_get_uid (comp, &uid);
+	e_cal_component_get_attachment_list (comp, &attach_list);
+	for (l = attach_list; l ; l = l->next){
+		if (!strncmp ((char *)l->data, "file://", 7)) {
+			fname = (char *)(l->data) + strlen ("file://");
+			filename = g_strrstr (fname, "/") + 1;
+			mime_filename = filename + strlen(uid) + 1;
+			attach_file = g_strdup (fname);
+		} else {
+			fname = (char *)(l->data);
+			filename = g_strrstr (fname, "/") + 1;
+			mime_filename = filename;
+			attach_file = g_strdup_printf ("%s/%s-%s", cbex->priv->local_attachment_store, uid, filename);
+		}
+	
+		file_contents = get_attach_file_contents (fname);
+		if (!file_contents)
+			continue;
+
+		len = strlen (file_contents);
+		dest_url = save_attach_file (attach_file, file_contents, len);
+		g_free (attach_file);
+		if (!dest_url)
+			continue;
+		new_attach_list = g_slist_append (new_attach_list, dest_url);
+
+		/* Content */
+		stream = camel_stream_mem_new_with_buffer (file_contents, len);
+		wrapper = camel_data_wrapper_new ();
+		camel_data_wrapper_construct_from_stream (wrapper, stream);
+		camel_object_unref (stream);
+
+		char *mime_type = gnome_vfs_get_mime_type (dest_url + strlen ("file://"));
+		type = camel_content_type_decode (mime_type);
+		camel_data_wrapper_set_mime_type_field (wrapper, type);
+		camel_content_type_unref (type);
+
+		mime_part = camel_mime_part_new ();
+
+		camel_medium_set_content_object (CAMEL_MEDIUM (mime_part), wrapper);
+		camel_mime_part_set_filename (mime_part, mime_filename);
+		camel_mime_part_set_encoding (mime_part, CAMEL_TRANSFER_ENCODING_BASE64);
+		cid = camel_header_msgid_generate ();
+		camel_mime_part_set_content_id (mime_part, cid);	
+		camel_mime_part_set_description (mime_part, mime_filename);
+		camel_mime_part_set_disposition (mime_part, "attachment");
+		camel_multipart_set_boundary (multipart, NULL);
+		*boundary = g_strdup (camel_multipart_get_boundary (multipart));
+		camel_multipart_add_part (multipart, mime_part);
+		camel_object_unref (mime_part);
+		g_free (cid);
+
+	}
+	if (!new_attach_list) {
+		camel_object_unref (multipart);
+		camel_object_unref (msg);
+		return NULL;
+	}
+	e_cal_component_set_attachment_list (comp, new_attach_list);
+
+	camel_medium_set_content_object (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (multipart));
+	camel_object_unref (multipart);
+
+	content = (CamelStreamMem *)camel_stream_mem_new();
+	dw = camel_medium_get_content_object (CAMEL_MEDIUM (msg));
+	camel_data_wrapper_decode_to_stream(dw, (CamelStream *)content);
+	buffer = g_memdup (content->buffer->data, content->buffer->len);
+	buffer[content->buffer->len] = '\0';
+	d(printf ("|| Buffer: \n%s\n", buffer));
+	camel_object_unref (content);
+	camel_object_unref (msg);
+
+	return buffer;
 }
 
 static ECalBackendSyncStatus
Index: calendar/e-cal-backend-exchange.h
===================================================================
RCS file: /cvs/gnome/evolution-exchange/calendar/e-cal-backend-exchange.h,v
retrieving revision 1.9
diff -u -p -u -r1.9 e-cal-backend-exchange.h
--- calendar/e-cal-backend-exchange.h	18 Jan 2005 11:56:08 -0000	1.9
+++ calendar/e-cal-backend-exchange.h	11 Mar 2005 14:22:25 -0000
@@ -92,6 +92,8 @@ void e_cal_backend_exchange_get_from (EC
 					char **from_name, char **from_addr);
 char * e_cal_backend_exchange_get_from_string (ECalBackendSync *backend, ECalComponent *comp); 
 gboolean e_cal_backend_exchange_is_online (ECalBackendExchange *cbex);
+GSList * get_attachment (ECalBackendExchange *cbex, const char *uid, const char *body, int len);
+char * build_msg ( ECalBackendExchange *cbex, ECalComponent *comp, const char *subject, char **boundary);
 
 G_END_DECLS
 
Index: calendar/e-cal-backend-exchange-calendar.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/calendar/e-cal-backend-exchange-calendar.c,v
retrieving revision 1.38
diff -u -p -u -r1.38 e-cal-backend-exchange-calendar.c
--- calendar/e-cal-backend-exchange-calendar.c	10 Mar 2005 10:02:58 -0000	1.38
+++ calendar/e-cal-backend-exchange-calendar.c	11 Mar 2005 14:22:25 -0000
@@ -25,11 +25,6 @@
 #include <sys/stat.h>
 #include <sys/fcntl.h>
 
-#include <camel/camel-mime-message.h>
-#include <camel/camel-multipart.h>
-#include <camel/camel-stream-mem.h>
-#include <camel/camel-file-utils.h>
-
 #include "e-cal-backend-exchange-calendar.h"
 
 #include "e2k-cal-utils.h"
@@ -56,12 +51,10 @@ enum {
 #define PARENT_TYPE E_TYPE_CAL_BACKEND_EXCHANGE
 static ECalBackendExchange *parent_class = NULL;
 
-#define d(x) (x)
+#define d(x)
 
 static ECalBackendSyncStatus modify_object_with_href (ECalBackendSync *backend, EDataCal *cal, const char *calobj, CalObjModType mod, char **old_object, const char *href);
 
-static GSList * get_attachment (ECalBackendExchange *cbex, const char *uid, const char *body, int len);
-
 gboolean check_for_send_options (icalcomponent *icalcomp, E2kProperties *props);
 
 static void
@@ -191,7 +184,6 @@ add_ical (ECalBackendExchange *cbex, con
 	if (uid)
 		attachment_list = get_attachment (cbex, uid, body, len);
 
-
 	start = g_strstr_len (body, len, "\nBEGIN:VCALENDAR");
 	if (!start)
 		return FALSE;
@@ -218,7 +210,6 @@ add_ical (ECalBackendExchange *cbex, con
 			ecomp = e_cal_component_new ();
 			e_cal_component_set_icalcomponent (ecomp, icalcomponent_new_clone (icalcomp));
 			e_cal_component_set_attachment_list (ecomp, attachment_list);
-			icalcomponent_free (icalcomp);
 			icalcomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (ecomp));
 			g_object_unref (ecomp);
 		}
@@ -235,14 +226,17 @@ add_ical (ECalBackendExchange *cbex, con
 	subcomp = icalcomponent_get_first_component (
 		icalcomp, ICAL_VEVENT_COMPONENT);
 	while (subcomp) {
-		new_comp = icalcomponent_new_clone (subcomp);
+		if (uid && !strcmp (uid, icalcomponent_get_uid (subcomp)) && attachment_list) {
+			ecomp = e_cal_component_new ();
+			e_cal_component_set_icalcomponent (ecomp, icalcomponent_new_clone (subcomp));
+			e_cal_component_set_attachment_list (ecomp, attachment_list);
+			new_comp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (ecomp));
+			g_object_unref (ecomp);
+		} else {
+			new_comp = icalcomponent_new_clone (subcomp);
+		}
+
 		if (new_comp) {
-			/*
-			if (attach_len) {
-				iattach = icalattach_new_from_data (attach_data, g_free, NULL);
-				attachment_list = g_slist_append (attachment_list, iattach);
-				e_cal_component_set_attachment_list (new_comp, attachment_list);
-			} */
 			add_vevent (cbex, href, lastmod, new_comp);
 			icalcomponent_free (new_comp);
 		}
@@ -254,77 +248,6 @@ add_ical (ECalBackendExchange *cbex, con
 	return TRUE;
 }
 
-static GSList * 
-get_attachment (ECalBackendExchange *cbex, const char *uid, 
-			const char *body, int len)
-{
-	CamelStream *stream;
-	CamelMimeMessage *msg;
-	CamelDataWrapper *content;
-	CamelMultipart *multipart;
-	CamelMimePart *part;
-	const char *filename = NULL;
-	char *attach_filename, *attach_file, *attach_file_url;
-	int fd;
-	int i;
-	GSList *list = NULL;
-	unsigned char *attach_data;
-
-	stream = camel_stream_mem_new_with_buffer (body, len);
-	msg = camel_mime_message_new ();
-	camel_data_wrapper_construct_from_stream (CAMEL_DATA_WRAPPER (msg), stream);
-	camel_object_unref (stream);
-
-	content = camel_medium_get_content_object (CAMEL_MEDIUM (msg));
-	if (CAMEL_IS_MULTIPART (content)) {
-		multipart = (CamelMultipart *)content;
-		content = NULL;
-	
-		for (i = 0; i < (int)camel_multipart_get_number (multipart); i++) {
-			part = camel_multipart_get_part (multipart, i);
-			filename = camel_mime_part_get_filename (part);
-			if (filename) {
-				content = camel_medium_get_content_object (CAMEL_MEDIUM (part));
-				break;
-			}
-		}
-	}
-
-	if (content) {
-		CamelStreamMem *stream_mem;
-		
-		stream = camel_stream_mem_new ();
-		stream_mem = (CamelStreamMem *)stream;
-	
-		camel_data_wrapper_decode_to_stream (content, stream);
-		attach_data = g_memdup (stream_mem->buffer->data, stream_mem->buffer->len);
-
-		// Attach
-		attach_filename = g_strdup_printf ("%s-%s", uid, filename);
-		attach_file = e_folder_exchange_get_storage_file (cbex->folder, attach_filename);
-		g_free (attach_filename);
-
-		fd = open (attach_file, O_RDWR|O_CREAT|O_TRUNC, 0600);
-		if (fd < 0) {
-			d(printf ("could not open file for creating attachment file locally\n"));
-		} else {
-			if (camel_write (fd, attach_data, stream_mem->buffer->len) < 0)
-				d(printf ("camel write to attach file failed\n"));
-		}
-		attach_file_url = g_strdup_printf ("file://%s", attach_file);
-		list = g_slist_append (list, g_strdup (attach_file_url));
-
-		close (fd);
-		g_free (attach_file_url);
-		g_free (attach_file);
-		
-		camel_object_unref (stream);
-	}
-	
-	camel_object_unref (msg);
-	return list;
-}
-
 static const char *event_properties[] = {
 	E2K_PR_CALENDAR_UID,
 	E2K_PR_DAV_LAST_MODIFIED,
@@ -336,7 +259,6 @@ static const int n_event_properties = G_
 
 static const char *new_event_properties[] = {
 	PR_INTERNET_CONTENT,
-	E2K_PR_HTTPMAIL_HAS_ATTACHMENT,
 	PR_READ_RECEIPT_REQUESTED,
 	PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED	
 };
@@ -592,120 +514,6 @@ add_timezone_cb (icalparameter *param, v
 		icalcomponent_add_component (cbdata->vcal_comp, vtzcomp);
 }
 
-static char *
-build_msg ( ECalBackendExchange *cbex, ECalComponent *comp, const char *subject, const char **boundary)
-{
-	CamelMimeMessage *msg;
-	CamelStreamMem *content;
-	CamelMimePart *mime_part;
-	CamelDataWrapper *dw, *wrapper;
-	CamelMultipart *multipart;
-	CamelInternetAddress *from;
-	CamelStream *stream;
-	CamelContentType *type;
-	char *buffer = NULL, *cid;
-	char *from_name, *from_email;
-	GSList *attach_list = NULL, *l, *new_attach_list = NULL;
-	char *fname, *filename = NULL, *file_contents = NULL, *dest_url, *dest_file;
-	int fd, len = 0;
-	struct stat sb;
-
-	e_cal_backend_exchange_get_from (E_CAL_BACKEND_SYNC (cbex), comp, &from_name, &from_email);
-
-	e_cal_component_get_attachment_list (comp, &attach_list);
-	for (l = attach_list; l ; l = l->next){
-		fname = (char *)l->data;
-	
-		filename = g_strrstr (fname, "/") + 1;
-
-		fd = open (fname, O_RDONLY);
-		if (fd < 0) {
-			d(printf ("Could not open the attachment file\n"));
-			continue;
-		}
-		if (fstat (fd, &sb) < 0) {
-			d(printf ("fstat of attachment file failed\n"));
-		}
-		len = sb.st_size;
-
-		file_contents = g_malloc0 (len + 1);
-
-		if (len > 0 && camel_read (fd, file_contents, len) < 0) {
-			d(printf ("reading from the attachment file failed\n"));
-			close (fd);
-		}
-		file_contents [len] = '\0';
-		close (fd);
-
-		/* Write it to our local exchange store in .evolution */
-		dest_file = e_folder_exchange_get_storage_file (cbex->folder, filename);
-		fd = open (dest_file, O_RDWR | O_CREAT | O_TRUNC, 0600);
-		if (fd < 0) {
-			d(printf ("open of destination file for attachments failed\n"));
-		}
-		
-		if (camel_write (fd, file_contents, len) < 0)
-			d(printf ("camel write to attach file failed\n"));
-		/* FIXME : Add a ATTACH:CID:someidentifier here */
-		dest_url = g_strconcat ("file:///", dest_file, NULL);
-		new_attach_list = g_slist_append (new_attach_list, dest_url);
-		g_free (dest_file);
-	}
-	e_cal_component_set_attachment_list (comp, new_attach_list);
-
-
-	if (len) {
-		msg = camel_mime_message_new ();
-
-		multipart = camel_multipart_new ();
-
-		/* Headers */
-		camel_mime_message_set_subject (msg, subject);
-
-		from = camel_internet_address_new ();
-		camel_internet_address_add (from, from_name, from_email);
-		camel_mime_message_set_from (msg, from);
-		camel_object_unref (from);
-		
-		/* Content */
-		stream = camel_stream_mem_new_with_buffer (file_contents, len);
-		wrapper = camel_data_wrapper_new ();
-		camel_data_wrapper_construct_from_stream (wrapper, stream);
-		camel_object_unref (stream);
-
-		type = camel_content_type_new ("text", "plain");
-		camel_content_type_set_param (type, "name", "\"test-attach.txt\"");
-		camel_data_wrapper_set_mime_type_field (wrapper, type);
-		camel_content_type_unref (type);
-
-		//mime_part = CAMEL_MIME_PART (msg);
-		mime_part = camel_mime_part_new ();
-
-		camel_medium_set_content_object (CAMEL_MEDIUM (mime_part), wrapper);
-		camel_mime_part_set_filename (mime_part, filename);
-		camel_mime_part_set_encoding (mime_part, CAMEL_TRANSFER_ENCODING_BASE64);
-		cid = camel_header_msgid_generate ();
-		camel_mime_part_set_content_id (mime_part, cid);	
-		camel_mime_part_set_description (mime_part, filename);
-		camel_mime_part_set_disposition (mime_part, "attachment");
-		camel_multipart_set_boundary (multipart, NULL);
-		*boundary = camel_multipart_get_boundary (multipart);
-		camel_multipart_add_part (multipart, mime_part);
-		camel_object_unref (mime_part);
-		camel_medium_set_content_object (CAMEL_MEDIUM (msg), CAMEL_DATA_WRAPPER (multipart));
-		camel_object_unref (multipart);
-
-		content = (CamelStreamMem *)camel_stream_mem_new();
-		dw = camel_medium_get_content_object (CAMEL_MEDIUM (msg));
-		camel_data_wrapper_decode_to_stream(dw, (CamelStream *)content);
-		buffer = g_memdup (content->buffer->data, content->buffer->len);
-		d(printf ("|| Buffer: \n%s\n", buffer));
-		g_free (cid);
-	}
-
-	return buffer;
-}
-
 gboolean
 check_for_send_options (icalcomponent *icalcomp, E2kProperties *props)
 {
@@ -759,7 +567,7 @@ create_object (ECalBackendSync *backend,
 	const char *summary;
 	char *attach_body = NULL;
 	char *attach_body_crlf = NULL;
-	const char *boundary;
+	char *boundary = NULL;
 	E2kHTTPStatus http_status;
 	E2kProperties *props = e2k_properties_new ();
 	E2kContext *e2kctx;
@@ -930,6 +738,7 @@ create_object (ECalBackendSync *backend,
 				       "\r\n%s\r\n%s", summary, date, boundary,
 				       from ? from : "Evolution", boundary,
 				       body_crlf, attach_body_crlf);
+		g_free (boundary);
 
 	} else {
 		msg = g_strdup_printf ("Subject: %s\r\n"
@@ -1106,6 +915,9 @@ modify_object_with_href (ECalBackendSync
 	const char *comp_uid;
 	char *updated_ecomp_str, *real_comp_str;
 	char *body, *body_crlf, *msg;
+	char *attach_body = NULL;
+	char *attach_body_crlf = NULL;
+	char *boundary = NULL;
 	struct icaltimetype last_modified;
 	icalcomponent_kind kind;
 	ECalComponentDateTime dt;
@@ -1147,6 +959,11 @@ modify_object_with_href (ECalBackendSync
 		return GNOME_Evolution_Calendar_ObjectNotFound;
 	}
 	
+	/* Fetch summary */
+	summary = icalcomponent_get_summary (icalcomp);
+	if (!summary)
+		summary = "";
+	
 	updated_ecomp = e_cal_component_new ();
 	e_cal_component_set_icalcomponent (updated_ecomp, icalcomp);
 
@@ -1154,7 +971,13 @@ modify_object_with_href (ECalBackendSync
 	
 	last_modified = icaltime_from_timet (time (NULL), 0);
 	e_cal_component_set_last_modified (updated_ecomp, &last_modified);
-	
+
+	if (e_cal_component_has_attachments (updated_ecomp)) {
+		d(printf ("This comp has attachments !!\n"));
+		attach_body = build_msg (E_CAL_BACKEND_EXCHANGE (cbexc), updated_ecomp, summary, &boundary);
+		attach_body_crlf = e_cal_backend_exchange_lf_to_crlf (attach_body);	
+	}
+
 	updated_ecomp_str = e_cal_component_get_as_string (updated_ecomp);
 	updated_icalcomp = icalparser_parse_string (updated_ecomp_str);
 	g_free (updated_ecomp_str);
@@ -1278,24 +1101,44 @@ modify_object_with_href (ECalBackendSync
 	date = e_cal_backend_exchange_make_timestamp_rfc822 (time (NULL));
 	from = e_cal_backend_exchange_get_from_string (backend, updated_ecomp);	
 	
-	summary = icalcomponent_get_summary (real_icalcomp);
-	if (!summary)
-		summary = "";
+	if (attach_body) {
+		msg = g_strdup_printf ("Subject: %s\r\n"
+				       "Date: %s\r\n"
+				       "MIME-Version: 1.0\r\n"
+				       "Content-Type: multipart/mixed;\r\n"
+				       "\tboundary=\"%s\";\r\n"
+				       "X-MS_Has-Attach: yes\r\n"
+				       "From: %s\r\n"
+					"\r\n--%s\r\n"
+				       "content-class: urn:content-classes:appointment\r\n"
+				       "Content-Type: text/calendar;\r\n"
+				       "\tmethod=REQUEST;\r\n"
+				       "\tcharset=\"utf-8\"\r\n"
+				       "Content-Transfer-Encoding: 8bit\r\n"
+				       "Importance: normal\r\n"
+				       "Priority: normal\r\n"
+				       "\r\n%s\r\n%s", summary, date, boundary,
+				       from ? from : "Evolution", boundary,
+				       body_crlf, attach_body_crlf);
+		g_free (boundary);
+
+	} else {
 
-	msg = g_strdup_printf ("Subject: %s\r\n"
-			       "Date: %s\r\n"
-			       "MIME-Version: 1.0\r\n"
-			       "Content-Type: text/calendar;\r\n"
-			       "\tmethod=REQUEST;\r\n"
-			       "\tcharset=\"utf-8\"\r\n"
-			       "Content-Transfer-Encoding: 8bit\r\n"
-			       "content-class: urn:content-classes:appointment\r\n"
-			       "Importance: normal\r\n"
-			       "Priority: normal\r\n"
-			       "From: %s\r\n"
-			       "\r\n%s", summary, date,
-			       from ? from : "Evolution",
-			       body_crlf);
+		msg = g_strdup_printf ("Subject: %s\r\n"
+				       "Date: %s\r\n"
+				       "MIME-Version: 1.0\r\n"
+				       "Content-Type: text/calendar;\r\n"
+				       "\tmethod=REQUEST;\r\n"
+				       "\tcharset=\"utf-8\"\r\n"
+				       "Content-Transfer-Encoding: 8bit\r\n"
+				       "content-class: urn:content-classes:appointment\r\n"
+				       "Importance: normal\r\n"
+				       "Priority: normal\r\n"
+				       "From: %s\r\n"
+				       "\r\n%s", summary, date,
+				       from ? from : "Evolution",
+				       body_crlf);
+	}
 	
 	g_free (date);
 	g_free (from);
Index: calendar/e-cal-backend-exchange-tasks.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/calendar/e-cal-backend-exchange-tasks.c,v
retrieving revision 1.14
diff -u -p -u -r1.14 e-cal-backend-exchange-tasks.c
--- calendar/e-cal-backend-exchange-tasks.c	10 Mar 2005 09:34:50 -0000	1.14
+++ calendar/e-cal-backend-exchange-tasks.c	11 Mar 2005 14:22:26 -0000
@@ -431,6 +431,7 @@ get_summary (ECalComponent *comp)
 static int
 put_body (ECalComponent *comp, E2kContext *ctx, E2kOperation *op,
          const char *uri, const char *from_name, const char *from_addr,
+	 const char *attach_body, const char *boundary,
          char **repl_uid)
 
 {
@@ -457,7 +458,41 @@ put_body (ECalComponent *comp, E2kContex
 	/* PUT the component on the server */
         desc_crlf = e2k_lf_to_crlf ((const char *) desc->str);
         date = e2k_make_timestamp_rfc822 (time (NULL));
-        body = g_strdup_printf ("content-class: urn:content-classes:task\r\n"
+	
+	if (attach_body) {
+		body = g_strdup_printf ("content-class: urn:content-classes:task\r\n"
+                                "Subject: %s\r\n"
+                                "Date: %s\r\n"
+                                "Message-ID: <%s>\r\n"
+                                "MIME-Version: 1.0\r\n"
+                                "Content-Type: multipart/mixed;\r\n"
+				"\tboundary=\"%s\";\r\n"
+				"X-MS_Has-Attach: yes\r\n"
+                                "From: \"%s\" <%s>\r\n"
+				"\r\n--%s\r\n"
+				"content-class: urn:content-classes:task\r\n"
+				"Content-Type: text/plain;\r\n"
+                                "\tcharset=\"utf-8\"\r\n"
+                                "Content-Transfer-Encoding: 8bit\r\n"
+                                "Thread-Topic: %s\r\n"
+                                "Priority: %s\r\n"
+                                "Importance: %s\r\n"
+                                "\r\n%s\r\n%s",
+                                get_summary (comp),
+                                date,
+                                get_uid (comp),
+				boundary,
+				from_name ? from_name : "Evolution",
+				from_addr ? from_addr : "",
+				boundary,
+                                get_summary (comp),
+                                get_priority (comp),
+                                get_priority (comp),
+                                desc_crlf,
+				attach_body);
+
+	} else {
+		body = g_strdup_printf ("content-class: urn:content-classes:task\r\n"
                                 "Subject: %s\r\n"
                                 "Date: %s\r\n"
                                 "Message-ID: <%s>\r\n"
@@ -479,6 +514,7 @@ put_body (ECalComponent *comp, E2kContex
                                 from_name ? from_name : "Evolution",
 				from_addr ? from_addr : "",
                                 desc_crlf);
+	}
 
         status = e2k_context_put (ctx, NULL, uri, "message/rfc822",
 				  body, strlen (body), NULL);
@@ -501,6 +537,7 @@ static const char *task_props[] = {
         E2K_PR_HTTPMAIL_SUBJECT,
         E2K_PR_HTTPMAIL_TEXT_DESCRIPTION,
         E2K_PR_HTTPMAIL_DATE,
+	E2K_PR_HTTPMAIL_HAS_ATTACHMENT,
         E2K_PR_CALENDAR_LAST_MODIFIED,
         E2K_PR_HTTPMAIL_FROM_EMAIL,
         E2K_PR_HTTPMAIL_FROM_NAME,
@@ -519,17 +556,20 @@ static const int n_task_props = sizeof (
 static guint
 get_changed_tasks (ECalBackendExchange *cbex, const char *since)
 {
+	ECalBackendExchangeComponent *ecalbexcomp;
 	E2kRestriction *rn;
 	E2kResultIter *iter;
 	GPtrArray *hrefs, *array;
-	GHashTable *modtimes;
+	GHashTable *modtimes, *attachments;
+	GSList *attachment_list = NULL;
 	E2kResult *result;
-	const char *modtime, *str;
-	char *uid;
+	E2kContext *ctx;
+	const char *modtime, *str, *prop;
+	char *uid, *body;
 	char *tzid;
 	int status, i, priority, percent;
 	float f_percent;
-	ECalComponent *ecal;
+	ECalComponent *ecal, *ecomp;
 	struct icaltimetype itt;
 	const icaltimezone *itzone;
 	ECalComponentDateTime ecdatetime;
@@ -564,6 +604,8 @@ get_changed_tasks (ECalBackendExchange *
 	hrefs = g_ptr_array_new ();
 	modtimes = g_hash_table_new_full (g_str_hash, g_str_equal,
 					  g_free, g_free);
+	attachments = g_hash_table_new_full (g_str_hash, g_str_equal,
+					  g_free, g_free);
 
 	while ((result = e2k_result_iter_next (iter))) {
 		uid = e2k_properties_get_prop (result->props,
@@ -753,7 +795,13 @@ get_changed_tasks (ECalBackendExchange *
 				E2K_PR_CALENDAR_URL))) {
 			e_cal_component_set_url (ecal, str);
 		}	
-		
+
+		/* Set Attachments */
+		if ((str = e2k_properties_get_prop (result->props,
+				E2K_PR_HTTPMAIL_HAS_ATTACHMENT))) {
+			g_hash_table_insert (attachments, g_strdup (result->href),
+				g_strdup (uid));
+		}
 		e_cal_component_commit_sequence (ecal);
 		icalcomp = e_cal_component_get_icalcomponent (ecal);
 		if (icalcomp)
@@ -765,6 +813,7 @@ get_changed_tasks (ECalBackendExchange *
 	if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
 		g_ptr_array_free (hrefs, TRUE);
 		g_hash_table_destroy (modtimes);
+		g_hash_table_destroy (attachments);
 		return status;
 	}
 
@@ -774,15 +823,86 @@ get_changed_tasks (ECalBackendExchange *
 	if (!hrefs->len) {
 		g_ptr_array_free (hrefs, TRUE);
 		g_hash_table_destroy (modtimes);
+		g_hash_table_destroy (attachments);
+		return SOUP_STATUS_OK;
+	}
+	
+	prop = PR_INTERNET_CONTENT;
+	iter = e_folder_exchange_bpropfind_start (cbex->folder, NULL,
+						(const char **)hrefs->pdata,
+						hrefs->len, &prop, 1);
+	for (i = 0; i < hrefs->len; i++)
+		g_free (hrefs->pdata[i]);
+	g_ptr_array_set_size (hrefs, 0);
+
+	while ((result = e2k_result_iter_next (iter))) {
+		GByteArray *ical_data;
+		ical_data = e2k_properties_get_prop (result->props, PR_INTERNET_CONTENT);
+		if (!ical_data) {
+			g_ptr_array_add (hrefs, g_strdup (result->href));
+			continue;
+		}
+
+		uid = g_hash_table_lookup (attachments, result->href);
+		/* Fetch component from cache and update it */
+		ecalbexcomp = get_exchange_comp (cbex, uid);
+		attachment_list = get_attachment (cbex, uid, ical_data->data, ical_data->len);
+		if (attachment_list) {
+			ecomp = e_cal_component_new ();
+			e_cal_component_set_icalcomponent (ecomp, icalcomponent_new_clone (ecalbexcomp->icomp));
+			e_cal_component_set_attachment_list (ecomp, attachment_list);
+			icalcomponent_free (ecalbexcomp->icomp);
+			ecalbexcomp->icomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (ecomp));
+			g_object_unref (ecomp);
+		}
+	}
+	status = e2k_result_iter_free (iter);
+
+	if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
+		g_ptr_array_free (hrefs, TRUE);
+		g_hash_table_destroy (attachments);
+		return status;
+	}
+
+	if (!hrefs->len) {
+		g_ptr_array_free (hrefs, TRUE);
+		g_hash_table_destroy (attachments);
 		return SOUP_STATUS_OK;
 	}
+
+	ctx = exchange_account_get_context (cbex->account);
+	if (!ctx) {
+		/* This either means we lost connection or we are in offline mode */
+		return SOUP_STATUS_CANT_CONNECT;
+	}
+
+	for (i = 0; i < hrefs->len; i++) {
+		int length;
 	
-	/* FIXME */
+		status = e2k_context_get (ctx, NULL, hrefs->pdata[i],
+					NULL, &body, &length);
+		if (!SOUP_STATUS_IS_SUCCESSFUL (status))
+			continue;
+		uid = g_hash_table_lookup (attachments, hrefs->pdata[i]);
+		/* Fetch component from cache and update it */
+		ecalbexcomp = get_exchange_comp (cbex, uid);
+		attachment_list = get_attachment (cbex, uid, body, length);
+		if (attachment_list) {
+			ecomp = e_cal_component_new ();
+			e_cal_component_set_icalcomponent (ecomp, icalcomponent_new_clone (ecalbexcomp->icomp));
+			e_cal_component_set_attachment_list (ecomp, attachment_list);
+			icalcomponent_free (ecalbexcomp->icomp);
+			ecalbexcomp->icomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (ecomp));
+			g_object_unref (ecomp);
+		}
+		g_free (body);
+	}
 
 	for (i = 0; i < hrefs->len; i++)
 		g_free (hrefs->pdata[i]);
 	g_ptr_array_free (hrefs, TRUE);
 	g_hash_table_destroy (modtimes);
+	g_hash_table_destroy (attachments);
 	return status;
 }
 
@@ -849,6 +969,9 @@ create_task_object (ECalBackendSync *bac
 	icalcomponent_kind kind;
 	struct icaltimetype current;
 	char *from_name, *from_addr;
+	char *boundary = NULL;
+	char *attach_body = NULL;
+	char *attach_body_crlf = NULL;
 	const char *summary;
 	char * modtime;
 	char *location;
@@ -882,6 +1005,10 @@ create_task_object (ECalBackendSync *bac
 	icalcomponent_add_property (icalcomp, icalproperty_new_lastmodified (current));
 
 	modtime = e2k_timestamp_from_icaltime (current);
+	
+	summary = icalcomponent_get_summary (icalcomp);
+	if (!summary)
+		summary = "";
 
 	/* Get the uid */
 	temp_comp_uid = icalcomponent_get_uid (icalcomp);
@@ -903,6 +1030,13 @@ create_task_object (ECalBackendSync *bac
 
 	get_from (backend, comp, &from_name, &from_addr);
 
+	/* Check for attachments */
+	if (e_cal_component_has_attachments (comp)) {
+		d(printf ("This task has attachments\n"));
+		attach_body = build_msg (ecalbex, comp, summary, &boundary);
+		attach_body_crlf = e_cal_backend_exchange_lf_to_crlf (attach_body);
+	}
+
 	props = e2k_properties_new ();
 
 	/* FIXME Check for props and its members */
@@ -939,9 +1073,6 @@ create_task_object (ECalBackendSync *bac
 	}
 
 	real_icalcomp = icalparser_parse_string (*calobj);
-	summary = e2k_properties_get_prop (props, E2K_PR_HTTPMAIL_THREAD_TOPIC);
-	if (!summary)
-		summary = g_strdup ("");
 
 	e2kctx = exchange_account_get_context (ecalbex->account);
 	status = e_folder_exchange_proppatch_new (ecalbex->folder, NULL,
@@ -949,7 +1080,8 @@ create_task_object (ECalBackendSync *bac
 						  props, &location, NULL );
 
 	if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
-		status = put_body(comp, e2kctx, NULL, location, from_name, from_addr, NULL);
+		status = put_body(comp, e2kctx, NULL, location, from_name, from_addr, 
+						attach_body_crlf, boundary, NULL);
 		if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
 			e_cal_backend_exchange_add_object (ecalbex, location, modtime, real_icalcomp);
 		}
@@ -975,6 +1107,9 @@ modify_task_object (ECalBackendSync *bac
 	const char* comp_uid, *summary;
 	char *from_name, *from_addr;
 	char *comp_str;
+	char *attach_body = NULL;
+	char *attach_body_crlf = NULL;
+	char *boundary = NULL;
 	struct icaltimetype current;
 	ECalBackendSyncStatus status;
 	E2kContext *e2kctx;
@@ -1021,6 +1156,9 @@ modify_task_object (ECalBackendSync *bac
 	*old_object = e_cal_component_get_as_string (cache_comp);
 	g_free (cache_comp);
 	
+	summary = icalcomponent_get_summary (icalcomp);
+	if (!summary)
+		summary = "";
 	/* Create the cal component */
         new_comp = e_cal_component_new ();
         e_cal_component_set_icalcomponent (new_comp, icalcomp);
@@ -1029,6 +1167,12 @@ modify_task_object (ECalBackendSync *bac
         current = icaltime_from_timet (time (NULL), 0);
         e_cal_component_set_last_modified (new_comp, &current);
 
+	/* Set Attachments */
+	if (e_cal_component_has_attachments (new_comp)) {
+		d(printf ("This task has attachments for modifications\n"));
+		attach_body = build_msg (ecalbex, new_comp, summary, &boundary);
+		attach_body_crlf = e_cal_backend_exchange_lf_to_crlf (attach_body);
+	}
 	comp_str = e_cal_component_get_as_string (new_comp);
 	icalcomp = icalparser_parse_string (comp_str);
 	g_free (comp_str);
@@ -1040,7 +1184,6 @@ modify_task_object (ECalBackendSync *bac
         props = e2k_properties_new ();
 
 	update_props (new_comp, &props);
-        summary = e2k_properties_get_prop (props, E2K_PR_HTTPMAIL_THREAD_TOPIC);  
 	e_cal_component_commit_sequence (new_comp);
 
         e2kctx = exchange_account_get_context (ecalbex->account);
@@ -1048,7 +1191,8 @@ modify_task_object (ECalBackendSync *bac
 	comp_str = e_cal_component_get_as_string (new_comp);
 	icalcomp = icalparser_parse_string (comp_str);
 	if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status)){
-		status = put_body(new_comp, e2kctx, NULL, ecalbexcomp->href, from_name, from_addr, NULL);
+		status = put_body(new_comp, e2kctx, NULL, ecalbexcomp->href, from_name, from_addr, 
+					attach_body_crlf, boundary, NULL);
 		if (E2K_HTTP_STATUS_IS_SUCCESSFUL (status))
 			e_cal_backend_exchange_modify_object (ecalbex, icalcomp, mod);
 	}


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