1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * JP Rosevear <jpr@ximian.com>
5 * Rodrigo Moya <rodrigo@ximian.com>
6 * Harish Krishnaswamy <kharish@novell.com>
7 * Copyright 2003, Novell, Inc.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of version 2 of the GNU Lesser General Public
11 * License as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
27 #include <sys/types.h>
37 #include <glib/gi18n.h>
38 #include <glib/gstdio.h>
40 #include <libgnomevfs/gnome-vfs-mime-utils.h>
41 #include <e-gw-connection.h>
42 #include <e-gw-message.h>
43 #include <libecal/e-cal-recur.h>
44 #include <libecal/e-cal-time-util.h>
45 #include <libsoup/soup-misc.h>
46 #include "e-cal-backend-groupwise-utils.h"
47 #include "libedataserver/e-source-list.h"
50 get_recur_instance (ECalComponent *comp, time_t instance_start, time_t instance_end, gpointer data)
52 GSList **recur_dates = (GSList **) data;
55 rdate = isodate_from_time_t (instance_start);
56 /* convert this into a date */
58 *recur_dates = g_slist_append (*recur_dates, rdate);
63 resolve_tzid_cb (const char *tzid, gpointer data)
65 /* do nothing.. since we are interested only in the event date */
70 e_cal_component_get_gw_id (ECalComponent *comp)
74 prop = icalcomponent_get_first_property (e_cal_component_get_icalcomponent (comp),
77 const char *x_name, *x_val;
79 x_name = icalproperty_get_x_name (prop);
80 x_val = icalproperty_get_x (prop);
81 if (!strcmp (x_name, "X-GWRECORDID")) {
85 prop = icalcomponent_get_next_property (e_cal_component_get_icalcomponent (comp),
92 set_categories_for_gw_item (EGwItem *item, GSList *category_names, ECalBackendGroupwise *cbgw)
94 GHashTable *categories_by_name, *categories_by_id;
103 categories_by_name = e_cal_backend_groupwise_get_categories_by_name (cbgw);
104 categories_by_id = e_cal_backend_groupwise_get_categories_by_id (cbgw);
105 cnc = e_cal_backend_groupwise_get_connection (cbgw);
107 g_return_if_fail (categories_by_id != NULL || categories_by_name != NULL || cnc != NULL);
109 for (; category_names != NULL; category_names = g_slist_next (category_names)) {
110 if (!category_names->data || strlen(category_names->data) == 0 )
112 id = g_hash_table_lookup (categories_by_name, category_names->data);
114 category_ids = g_list_append (category_ids, g_strdup (id));
116 EGwItem *category_item;
117 category_item = e_gw_item_new_empty();
118 e_gw_item_set_item_type (category_item, E_GW_ITEM_TYPE_CATEGORY);
119 e_gw_item_set_category_name (category_item, category_names->data);
120 status = e_gw_connection_create_item (cnc, category_item, &id);
121 if (status == E_GW_CONNECTION_STATUS_OK && id != NULL) {
122 char **components = g_strsplit (id, "@", -1);
123 char *temp_id = components[0];
125 g_hash_table_insert (categories_by_name, g_strdup (category_names->data), g_strdup(temp_id));
126 g_hash_table_insert (categories_by_id, g_strdup(temp_id), g_strdup (category_names->data));
127 category_ids = g_list_append (category_ids, g_strdup(temp_id));
129 g_strfreev(components);
131 g_object_unref (category_item);
134 e_gw_item_set_categories (item, category_ids);
138 add_send_options_data_to_item (EGwItem *item, ECalComponent *comp, icaltimezone *default_zone)
142 icalcomponent *icalcomp;
143 icalproperty *icalprop;
144 struct icaltimetype temp;
145 gboolean sendoptions_set = FALSE;
148 utc = icaltimezone_get_utc_timezone ();
149 icalcomp = e_cal_component_get_icalcomponent (comp);
150 icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
154 x_name = icalproperty_get_x_name (icalprop);
156 if (!strcmp (x_name, "X-EVOLUTION-OPTIONS-PRIORITY")) {
157 sendoptions_set = TRUE;
158 x_val = icalproperty_get_x (icalprop);
159 switch (atoi (x_val)) {
160 case 1: e_gw_item_set_priority (item, E_GW_ITEM_PRIORITY_HIGH);
162 case 2: e_gw_item_set_priority (item, E_GW_ITEM_PRIORITY_STANDARD);
164 case 3: e_gw_item_set_priority (item, E_GW_ITEM_PRIORITY_LOW);
166 default: e_gw_item_set_priority (item, NULL);
169 } else if (!strcmp (x_name, "X-EVOLUTION-OPTIONS-REPLY")) {
170 e_gw_item_set_reply_request (item, TRUE);
171 x_val = icalproperty_get_x (icalprop);
172 if (strcmp (x_val, "convenient")) {
174 int i = atoi (x_val);
175 temp = icaltime_current_time_with_zone (default_zone ? default_zone : utc);
176 icaltime_adjust (&temp, i, 0, 0, 0);
177 icaltime_set_timezone (&temp, default_zone);
178 temp = icaltime_convert_to_zone (temp, utc);
179 value = icaltime_as_ical_string (temp);
180 e_gw_item_set_reply_within (item, (char *) value);
182 } else if (!strcmp (x_name, "X-EVOLUTION-OPTIONS-EXPIRE")) {
183 const char *expire = NULL;
184 x_val = icalproperty_get_x (icalprop);
185 temp = icaltime_current_time_with_zone (default_zone ? default_zone : utc);
186 icaltime_adjust (&temp, atoi (x_val), 0, 0, 0);
187 icaltime_set_timezone (&temp, default_zone);
188 temp = icaltime_convert_to_zone (temp, utc);
189 expire = icaltime_as_ical_string (temp);
190 e_gw_item_set_expires (item, (char *) expire);
192 } else if (!strcmp (x_name, "X-EVOLUTION-OPTIONS-DELAY")) {
193 const char *delay = NULL;
194 x_val = icalproperty_get_x (icalprop);
195 temp = icaltime_from_string (x_val);
196 icaltime_set_timezone (&temp, default_zone);
197 temp = icaltime_convert_to_zone (temp, utc);
198 delay = icaltime_as_ical_string (temp);
199 e_gw_item_set_delay_until (item, (char *) delay);
201 } else if (!strcmp (x_name, "X-EVOLUTION-OPTIONS-TRACKINFO")) {
202 sendoptions_set = TRUE;
203 x_val = icalproperty_get_x (icalprop);
204 switch (atoi (x_val)) {
205 case 1: e_gw_item_set_track_info (item, E_GW_ITEM_DELIVERED);
207 case 2: e_gw_item_set_track_info (item, E_GW_ITEM_DELIVERED_OPENED);
209 case 3: e_gw_item_set_track_info (item, E_GW_ITEM_ALL);
211 default: e_gw_item_set_track_info (item, E_GW_ITEM_NONE);
214 } else if (!strcmp (x_name, "X-EVOLUTION-OPTIONS-OPENED")) {
216 x_val = icalproperty_get_x (icalprop);
219 case 0: e_gw_item_set_notify_opened (item, E_GW_ITEM_NOTIFY_NONE);
221 case 1: e_gw_item_set_notify_opened (item, E_GW_ITEM_NOTIFY_MAIL);
224 } else if (!strcmp (x_name, "X-EVOLUTION-OPTIONS-ACCEPTED")) {
226 x_val = icalproperty_get_x (icalprop);
229 case 0: e_gw_item_set_notify_accepted (item, E_GW_ITEM_NOTIFY_NONE);
231 case 1: e_gw_item_set_notify_accepted (item, E_GW_ITEM_NOTIFY_MAIL);
234 } else if (!strcmp (x_name, "X-EVOLUTION-OPTIONS-DECLINED")) {
236 x_val = icalproperty_get_x (icalprop);
239 case 0: e_gw_item_set_notify_declined (item, E_GW_ITEM_NOTIFY_NONE);
241 case 1: e_gw_item_set_notify_declined (item, E_GW_ITEM_NOTIFY_MAIL);
244 } else if (!strcmp (x_name, "X-EVOLUTION-OPTIONS-COMPLETED")) {
246 x_val = icalproperty_get_x (icalprop);
249 case 0: e_gw_item_set_notify_completed (item, E_GW_ITEM_NOTIFY_NONE);
251 case 1: e_gw_item_set_notify_completed (item, E_GW_ITEM_NOTIFY_MAIL);
255 icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
258 e_gw_item_set_sendoptions (item, sendoptions_set);
263 e_cal_backend_groupwise_set_attachments_from_comp (ECalComponent *comp,
266 GSList *attach_list = NULL, *attach_file_list = NULL;
269 e_cal_component_get_attachment_list (comp, &attach_file_list);
271 for (l = attach_file_list; l ; l = l->next) {
273 EGwItemAttachment *attach_item;
274 char *file_contents, *encoded_data;
276 char *attach_filename_full, *filename;
279 attach_filename_full = g_filename_from_uri ((char *)l->data, NULL, NULL);
280 if (!g_file_get_contents (attach_filename_full, &file_contents, &file_len, NULL)) {
281 g_message ("DEBUG: could not read %s\n", attach_filename_full);
282 g_free (attach_filename_full);
286 /* Extract the simple file name from the
287 * attach_filename_full which is of the form
288 * file://<path>/compuid-<simple filename>
290 e_cal_component_get_uid (comp, &uid);
291 filename = g_strrstr (attach_filename_full, uid);
292 if (filename == NULL) {
293 g_message ("DEBUG: This is an invalid attachment file\n");
294 g_free (attach_filename_full);
295 g_free (file_contents);
299 attach_item = g_new0 (EGwItemAttachment, 1);
300 /* FIXME the member does not follow the naming convention.
301 * Should be fixed in e-gw-item*/
302 attach_item->contentType = g_strdup (gnome_vfs_get_mime_type (attach_filename_full));
303 g_free (attach_filename_full);
305 attach_item->name = g_strdup (filename + strlen(uid) + 1);
306 /* do a base64 encoding so it can be embedded in a soap
308 encoded_data = soup_base64_encode (file_contents, file_len);
309 attach_item->data = encoded_data;
310 attach_item->size = strlen (encoded_data);
312 g_free (file_contents);
313 attach_list = g_slist_append (attach_list, attach_item);
316 e_gw_item_set_attach_id_list (item, attach_list);
319 /* Returns the icalproperty for the Attendee associted with email id */
320 static icalproperty *
321 get_attendee_prop (icalcomponent *icalcomp, const char *attendee)
325 for (prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
327 prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY)) {
328 const char *att = icalproperty_get_attendee (prop);
330 if (!g_ascii_strcasecmp (att, attendee)) {
338 /* get_attendee_list from cal comp and convert into
339 * egwitemrecipient and set it on recipient_list*/
341 set_attendees_to_item (EGwItem *item, ECalComponent *comp, icaltimezone *default_zone, gboolean delegate, const char *user_email)
343 if (e_cal_component_get_vtype (comp) == E_CAL_COMPONENT_JOURNAL) {
344 if (e_cal_component_has_organizer (comp)) {
345 icalcomponent *icalcomp = e_cal_component_get_icalcomponent (comp);
346 icalproperty *icalprop;
347 GSList *recipient_list = NULL;
348 const char *attendees = NULL;
349 char **emails, **iter;
351 for (icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY); icalprop;
352 icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY)) {
353 if (g_str_equal (icalproperty_get_x_name (icalprop), "X-EVOLUTION-RECIPIENTS")) {
359 attendees = icalproperty_get_x (icalprop);
360 emails = g_strsplit (attendees, ";", -1);
364 EGwItemRecipient *recipient;
366 recipient = g_new0 (EGwItemRecipient, 1);
368 recipient->email = g_strdup (*iter);
369 recipient->type = E_GW_ITEM_RECIPIENT_TO;
371 recipient_list = g_slist_prepend (recipient_list, recipient);
375 e_gw_item_set_recipient_list (item, recipient_list);
378 icalcomponent_remove_property (icalcomp, icalprop);
379 icalproperty_free (icalprop);
382 } else if (e_cal_component_has_attendees (comp)) {
383 GSList *attendee_list, *recipient_list = NULL, *al;
385 e_cal_component_get_attendee_list (comp, &attendee_list);
386 for (al = attendee_list; al != NULL; al = al->next) {
387 ECalComponentAttendee *attendee = (ECalComponentAttendee *) al->data;
388 EGwItemRecipient *recipient;
390 if (delegate && (g_str_equal (attendee->value + 7, user_email) || !(attendee->delfrom && *attendee->delfrom)))
394 icalproperty *prop = get_attendee_prop (e_cal_component_get_icalcomponent (comp),
397 icalproperty_remove_parameter_by_kind (prop, ICAL_DELEGATEDFROM_PARAMETER);
400 recipient = g_new0 (EGwItemRecipient, 1);
402 /* len (MAILTO:) + 1 = 7 */
403 recipient->email = g_strdup (attendee->value + 7);
404 if (attendee->cn != NULL)
405 recipient->display_name = g_strdup (attendee->cn);
406 if (attendee->role == ICAL_ROLE_REQPARTICIPANT)
407 recipient->type = E_GW_ITEM_RECIPIENT_TO;
408 else if (attendee->role == ICAL_ROLE_OPTPARTICIPANT)
409 recipient->type = E_GW_ITEM_RECIPIENT_CC;
410 else recipient->type = E_GW_ITEM_RECIPIENT_NONE;
412 if (attendee->status == ICAL_PARTSTAT_ACCEPTED)
413 recipient->status = E_GW_ITEM_STAT_ACCEPTED;
414 else if (attendee->status == ICAL_PARTSTAT_DECLINED)
415 recipient->status = E_GW_ITEM_STAT_DECLINED;
417 recipient->status = E_GW_ITEM_STAT_NONE;
419 recipient_list = g_slist_append (recipient_list, recipient);
422 e_cal_component_free_attendee_list(attendee_list);
424 /* recipient_list shouldn't be freed. Look into the function below. */
425 e_gw_item_set_recipient_list (item, recipient_list);
428 if (e_cal_component_has_organizer (comp)) {
430 add_send_options_data_to_item (item, comp, default_zone);
433 if (!delegate && e_cal_component_has_organizer (comp)) {
434 ECalComponentOrganizer cal_organizer;
435 EGwItemOrganizer *organizer = NULL;
437 e_cal_component_get_organizer (comp, &cal_organizer);
438 organizer = g_new0 (EGwItemOrganizer, 1);
439 organizer->display_name = g_strdup (cal_organizer.cn);
440 organizer->email = g_strdup (cal_organizer.value + 7);
441 e_gw_item_set_organizer (item, organizer);
447 set_rrule_from_comp (ECalComponent *comp, EGwItem *item, ECalBackendGroupwise *cbgw)
450 EGwItemRecurrenceRule *item_rrule;
451 struct icalrecurrencetype *ical_recur;
452 GSList *rrule_list = NULL, *exdate_list;
455 item_rrule = g_new0 (EGwItemRecurrenceRule, 1);
456 e_cal_component_get_rrule_list (comp, &rrule_list);
458 /* assumes only one rrule is present */
459 ical_recur = (struct icalrecurrencetype *) rrule_list->data;
461 g_message ("DEBUG: Processing rule\n%s\n", icalrecurrencetype_as_string (ical_recur));
463 switch (ical_recur->freq) {
464 case ICAL_DAILY_RECURRENCE :
465 item_rrule->frequency = E_GW_ITEM_RECURRENCE_FREQUENCY_DAILY;
467 case ICAL_WEEKLY_RECURRENCE:
468 item_rrule->frequency = E_GW_ITEM_RECURRENCE_FREQUENCY_WEEKLY;
470 case ICAL_MONTHLY_RECURRENCE:
471 item_rrule->frequency = E_GW_ITEM_RECURRENCE_FREQUENCY_MONTHLY;
473 case ICAL_YEARLY_RECURRENCE:
474 item_rrule->frequency = E_GW_ITEM_RECURRENCE_FREQUENCY_YEARLY;
479 if (ical_recur->count != 0)
480 item_rrule->count = ical_recur->count;
482 item_rrule->until = g_strdup (icaltime_as_ical_string (ical_recur->until));
484 item_rrule->interval = ical_recur->interval;
486 /*xxx -byday, bymonthday and byyearday not handled FIXME*/
487 for (i = 0; i < ICAL_BY_DAY_SIZE; i++)
488 item_rrule->by_day[i] = ical_recur->by_day[i];
489 for (i = 0; i < ICAL_BY_MONTHDAY_SIZE; i++)
490 item_rrule->by_month_day[i] = ical_recur->by_month_day[i];
491 for (i = 0; i < ICAL_BY_YEARDAY_SIZE; i++)
492 item_rrule->by_year_day[i] = ical_recur->by_year_day[i];
493 for (i = 0; i < ICAL_BY_MONTH_SIZE; i++)
494 item_rrule->by_month[i] = ical_recur->by_month[i];
496 e_gw_item_set_rrule (item, item_rrule);
499 if (e_cal_component_has_exdates (comp)) {
500 GSList *l, *item_exdate_list = NULL;
501 icaltimezone *default_zone, *utc;
502 struct icaltimetype itt_utc;
505 e_cal_component_get_exdate_list (comp, &exdate_list);
506 default_zone = e_cal_backend_groupwise_get_default_zone (cbgw);
507 utc = icaltimezone_get_utc_timezone ();
508 for (l = exdate_list; l ; l = l->next) {
509 ECalComponentDateTime *dt = (ECalComponentDateTime *) l->data;
511 if (!icaltime_get_timezone (*(dt->value)))
512 icaltime_set_timezone (dt->value, default_zone ? default_zone : utc);
513 itt_utc = icaltime_convert_to_zone (*dt->value, utc);
514 item_exdate_list = g_slist_append (item_exdate_list, g_strdup (icaltime_as_ical_string (itt_utc)));
517 e_gw_item_set_exdate_list (item, item_exdate_list);
518 e_cal_component_free_exdate_list (exdate_list);
524 set_properties_from_cal_component (EGwItem *item, ECalComponent *comp, ECalBackendGroupwise *cbgw)
526 const char *uid, *location;
527 ECalComponentDateTime dt;
528 ECalComponentClassification classif;
529 ECalComponentTransparency transp;
530 ECalComponentText text;
534 icaltimezone *default_zone, *utc;
535 struct icaltimetype itt_utc;
537 default_zone = e_cal_backend_groupwise_get_default_zone (cbgw);
538 utc = icaltimezone_get_utc_timezone ();
540 /* first set specific properties */
541 switch (e_cal_component_get_vtype (comp)) {
542 case E_CAL_COMPONENT_EVENT :
543 e_gw_item_set_item_type (item, E_GW_ITEM_TYPE_APPOINTMENT);
546 e_cal_component_get_transparency (comp, &transp);
547 if (transp == E_CAL_COMPONENT_TRANSP_OPAQUE)
548 e_gw_item_set_accept_level (item, E_GW_ITEM_ACCEPT_LEVEL_BUSY);
550 e_gw_item_set_accept_level (item, E_GW_ITEM_ACCEPT_LEVEL_FREE);
553 e_cal_component_get_location (comp, &location);
554 e_gw_item_set_place (item, location);
557 e_cal_component_get_categories_list (comp, &categories);
558 set_categories_for_gw_item (item, categories, cbgw);
561 if (e_cal_component_has_alarms (comp)) {
562 ECalComponentAlarm *alarm;
563 ECalComponentAlarmTrigger trigger;
565 GList *l = e_cal_component_get_alarm_uids (comp);
567 alarm = e_cal_component_get_alarm (comp, l->data);
568 e_cal_component_alarm_get_trigger (alarm, &trigger);
569 duration = abs (icaldurationtype_as_int (trigger.u.rel_duration));
570 e_gw_item_set_trigger (item, duration);
576 e_cal_component_get_dtend (comp, &dt);
578 if (!icaltime_get_timezone (*dt.value))
579 icaltime_set_timezone (dt.value, default_zone ? default_zone : utc);
580 itt_utc = icaltime_convert_to_zone (*dt.value, utc);
581 e_gw_item_set_end_date (item, icaltime_as_ical_string (itt_utc));
586 case E_CAL_COMPONENT_TODO :
587 e_gw_item_set_item_type (item, E_GW_ITEM_TYPE_TASK);
590 e_cal_component_get_due (comp, &dt);
592 if (!icaltime_get_timezone (*dt.value))
593 icaltime_set_timezone (dt.value, default_zone);
594 itt_utc = icaltime_convert_to_zone (*dt.value, utc);
595 e_gw_item_set_due_date (item, icaltime_as_ical_string (itt_utc));
600 e_cal_component_get_priority (comp, &priority);
601 if (priority && *priority) {
603 e_gw_item_set_task_priority (item, E_GW_ITEM_PRIORITY_LOW);
604 else if (*priority >= 5)
605 e_gw_item_set_task_priority (item, E_GW_ITEM_PRIORITY_STANDARD);
606 else if (*priority >= 1)
607 e_gw_item_set_task_priority (item, E_GW_ITEM_PRIORITY_HIGH);
609 e_gw_item_set_task_priority (item, NULL);
611 e_cal_component_free_priority (priority);
615 e_cal_component_get_completed (comp, &dt.value);
617 e_gw_item_set_completed (item, TRUE);
619 e_gw_item_set_completed (item, FALSE);
622 case E_CAL_COMPONENT_JOURNAL:
623 e_gw_item_set_item_type (item, E_GW_ITEM_TYPE_NOTE);
626 g_object_unref (item);
630 /* set common properties */
632 e_gw_item_set_id (item, e_cal_component_get_gw_id (comp));
636 e_cal_component_get_uid (comp, &uid);
637 e_gw_item_set_icalid (item, uid);
640 e_cal_component_get_summary (comp, &text);
641 e_gw_item_set_subject (item, text.value);
644 e_cal_component_get_description_list (comp, &slist);
646 GString *str = g_string_new ("");
648 for (sl = slist; sl != NULL; sl = sl->next) {
649 ECalComponentText *pt = sl->data;
652 str = g_string_append (str, pt->value);
655 e_gw_item_set_message (item, (const char *) str->str);
657 g_string_free (str, TRUE);
658 e_cal_component_free_text_list (slist);
663 e_cal_component_get_dtstart (comp, &dt);
665 if (!icaltime_get_timezone (*dt.value))
666 icaltime_set_timezone (dt.value, default_zone);
667 itt_utc = icaltime_convert_to_zone (*dt.value, utc);
668 e_gw_item_set_start_date (item, icaltime_as_ical_string (itt_utc));
669 } else if (e_gw_item_get_item_type (item) == E_GW_ITEM_TYPE_APPOINTMENT) {
670 /* appointments need the start date property */
671 g_object_unref (item);
676 if (dt.value && dt.value->is_date && e_gw_item_get_item_type (item) == E_GW_ITEM_TYPE_APPOINTMENT)
677 e_gw_item_set_is_allday_event (item, TRUE);
680 e_cal_component_get_created (comp, &dt.value);
682 if (!icaltime_get_timezone (*dt.value))
683 icaltime_set_timezone (dt.value, default_zone);
684 itt_utc = icaltime_convert_to_zone (*dt.value, utc);
685 e_gw_item_set_creation_date (item, icaltime_as_ical_string (itt_utc));
687 struct icaltimetype itt;
689 e_cal_component_get_dtstamp (comp, &itt);
690 e_gw_item_set_creation_date (item, icaltime_as_ical_string (itt));
694 e_cal_component_get_classification (comp, &classif);
696 case E_CAL_COMPONENT_CLASS_PUBLIC :
697 e_gw_item_set_classification (item, E_GW_ITEM_CLASSIFICATION_PUBLIC);
699 case E_CAL_COMPONENT_CLASS_PRIVATE :
700 e_gw_item_set_classification (item, E_GW_ITEM_CLASSIFICATION_PRIVATE);
702 case E_CAL_COMPONENT_CLASS_CONFIDENTIAL :
703 e_gw_item_set_classification (item, E_GW_ITEM_CLASSIFICATION_CONFIDENTIAL);
706 e_gw_item_set_classification (item, NULL);
710 set_attendees_to_item (item, comp, default_zone, FALSE, NULL);
712 /* check if recurrences exist and update the item */
713 if (e_cal_component_has_recurrences (comp)) {
714 if (e_cal_component_has_rrules (comp))
715 set_rrule_from_comp (comp, item, cbgw);
718 GSList *recur_dates = NULL;
721 e_cal_recur_generate_instances (comp, -1, -1,get_recur_instance, &recur_dates, resolve_tzid_cb, NULL, (icaltimezone *) default_zone);
723 e_cal_recur_generate_instances (comp, -1, -1,get_recur_instance, &recur_dates, resolve_tzid_cb, NULL, utc);
725 recur_dates = g_slist_delete_link (recur_dates, recur_dates);
727 e_gw_item_set_recurrence_dates (item, recur_dates);
732 if (e_cal_component_has_attachments (comp)) {
733 e_cal_backend_groupwise_set_attachments_from_comp (comp, item);
740 e_gw_item_new_from_cal_component (const char *container, ECalBackendGroupwise *cbgw, ECalComponent *comp)
744 g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
746 item = e_gw_item_new_empty ();
747 e_gw_item_set_container_id (item, container);
748 return set_properties_from_cal_component (item, comp, cbgw);
751 /* Set the attendee list and send options to EGwItem */
753 e_gw_item_new_for_delegate_from_cal (ECalBackendGroupwise *cbgw, ECalComponent *comp)
756 icaltimezone *default_zone;
757 const char *user_email;
759 g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL);
760 default_zone = e_cal_backend_groupwise_get_default_zone (cbgw);
761 item = e_gw_item_new_empty ();
762 e_gw_item_set_id (item, e_cal_component_get_gw_id (comp));
763 user_email = e_gw_connection_get_user_email (e_cal_backend_groupwise_get_connection (cbgw));
765 set_attendees_to_item (item, comp, default_zone, TRUE, user_email);
766 add_send_options_data_to_item (item, comp, default_zone);
771 /* Fetch data from the server and unencode it to the actual data
772 * and populate the attach_data
775 get_attach_data_from_server (EGwItemAttachment *attach_item, ECalBackendGroupwise *cbgw)
778 EGwConnectionStatus status;
782 cnc = e_cal_backend_groupwise_get_connection (cbgw);
783 g_return_val_if_fail (E_IS_GW_CONNECTION (cnc), E_GW_CONNECTION_STATUS_INVALID_CONNECTION);
785 status = e_gw_connection_get_attachment (cnc, attach_item->id, 0, -1, (const char **) &data, &len);
787 if (status != E_GW_CONNECTION_STATUS_OK ) {
788 g_warning ("Failed to read the attachment from the server\n");
791 attach_item->data = data;
792 attach_item->size = len;
798 set_attachments_to_cal_component (EGwItem *item, ECalComponent *comp, ECalBackendGroupwise *cbgw)
800 GSList *fetch_list = NULL, *l;
801 GSList *comp_attachment_list = NULL;
803 char *attach_file_url;
805 fetch_list = e_gw_item_get_attach_id_list (item);
806 if (fetch_list == NULL)
807 return; /* No attachments exist */
809 e_cal_component_get_uid (comp, &uid);
810 for (l = fetch_list; l ; l = l->next) {
812 EGwItemAttachment *attach_item;
813 char *attach_data = NULL;
817 attach_item = (EGwItemAttachment *) l->data;
818 attach_file_url = g_strconcat (e_cal_backend_groupwise_get_local_attachments_store (cbgw),
819 "/", uid, "-", attach_item->name, NULL);
821 filename = g_filename_from_uri (attach_file_url, NULL, NULL);
822 if (g_stat (filename, &st) == -1) {
823 if (!get_attach_data_from_server (attach_item, cbgw)) {
825 return; /* Could not get the attachment from the server */
827 fd = g_open (filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600);
829 /* skip gracefully */
830 g_warning ("DEBUG: could not serialize attachments\n");
831 } else if (write (fd, attach_item->data, attach_item->size) == -1) {
832 /* skip gracefully */
833 g_warning ("DEBUG: attachment write failed.\n");
835 g_free (attach_data);
841 comp_attachment_list = g_slist_append (comp_attachment_list, attach_file_url);
844 e_cal_component_set_attachment_list (comp, comp_attachment_list);
849 set_default_alarms (ECalComponent *comp)
852 GConfClient *gconf = gconf_client_get_default ();
854 if (gconf_client_get_bool (gconf, CALENDAR_CONFIG_DEFAULT_REMINDER, NULL)) {
856 ECalComponentAlarm *acomp;
864 ECalComponentAlarmTrigger trigger;
866 interval = gconf_client_get_int (gconf, CALENDAR_CONFIG_DEFAULT_REMINDER_INTERVAL, NULL);
867 units = gconf_client_get_string (gconf, CALENDAR_CONFIG_DEFAULT_REMINDER_UNITS, NULL);
872 if (!strcmp (units, "days"))
874 else if (!strcmp (units, "hours"))
880 acomp = e_cal_component_alarm_new ();
882 e_cal_component_alarm_set_action (acomp, E_CAL_COMPONENT_ALARM_DISPLAY);
884 trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
885 memset (&trigger.u.rel_duration, 0, sizeof (trigger.u.rel_duration));
887 trigger.u.rel_duration.is_neg = TRUE;
891 trigger.u.rel_duration.minutes = interval;
894 trigger.u.rel_duration.hours = interval;
897 trigger.u.rel_duration.days = interval;
900 e_cal_component_alarm_free (acomp);
901 g_object_unref (gconf);
905 e_cal_component_alarm_set_trigger (acomp, trigger);
906 e_cal_component_add_alarm (comp, acomp);
908 e_cal_component_alarm_free (acomp);
910 g_object_unref (gconf);
915 e_gw_item_to_cal_component (EGwItem *item, ECalBackendGroupwise *cbgw)
918 ECalComponentText text;
919 ECalComponentDateTime dt;
920 const char *description, *uid;
924 GHashTable *categories_by_id;
926 icaltimezone *default_zone;
928 struct icaltimetype itt, itt_utc;
932 GSList *recipient_list, *rl, *attendee_list = NULL;
933 EGwItemOrganizer *organizer;
934 EGwItemType item_type;
936 default_zone = e_cal_backend_groupwise_get_default_zone (cbgw);
937 categories_by_id = e_cal_backend_groupwise_get_categories_by_id (cbgw);
939 g_return_val_if_fail (E_IS_GW_ITEM (item), NULL);
941 comp = e_cal_component_new ();
943 item_type = e_gw_item_get_item_type (item);
945 if (item_type == E_GW_ITEM_TYPE_APPOINTMENT)
946 e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
947 else if (item_type == E_GW_ITEM_TYPE_TASK)
948 e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
949 else if (item_type == E_GW_ITEM_TYPE_NOTE)
950 e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
952 g_object_unref (comp);
956 /* set common properties */
958 description = e_gw_item_get_id (item);
960 icalproperty *icalprop;
962 icalprop = icalproperty_new_x (description);
963 icalproperty_set_x_name (icalprop, "X-GWRECORDID");
964 icalcomponent_add_property (e_cal_component_get_icalcomponent (comp), icalprop);
968 if (e_gw_item_get_reply_request (item)) {
970 const char *mess = e_gw_item_get_message (item);
973 reply_within = e_gw_item_get_reply_within (item);
978 t = e_gw_connection_get_date_from_string (reply_within);
980 temp [strlen (temp)-1] = '\0';
981 value = g_strconcat (N_("Reply Requested: by "), temp, "\n\n", mess ? mess : "", NULL);
982 e_gw_item_set_message (item, (const char *) value);
986 value = g_strconcat (N_("Reply Requested: When convenient"), "\n\n", mess ? mess : "", NULL);
987 e_gw_item_set_message (item, (const char *) value);
993 text.value = e_gw_item_get_subject (item);
995 e_cal_component_set_summary (comp, &text);
998 description = e_gw_item_get_message (item);
1002 text.value = description;
1007 e_cal_component_set_description_list (comp, &l);
1011 t = e_gw_item_get_creation_date (item);
1013 itt_utc = icaltime_from_string (t);
1014 if (!icaltime_get_timezone (itt_utc))
1015 icaltime_set_timezone (&itt_utc, icaltimezone_get_utc_timezone());
1017 itt = icaltime_convert_to_zone (itt_utc, default_zone);
1018 icaltime_set_timezone (&itt, default_zone);
1019 e_cal_component_set_created (comp, &itt);
1020 e_cal_component_set_dtstamp (comp, &itt);
1023 e_cal_component_set_created (comp, &itt_utc);
1024 e_cal_component_set_dtstamp (comp, &itt_utc);
1030 category_ids = e_gw_item_get_categories (item);
1032 if (category_ids && categories_by_id) {
1033 for (; category_ids != NULL; category_ids = g_list_next (category_ids)) {
1034 name = g_hash_table_lookup (categories_by_id, category_ids->data);
1036 categories = g_slist_append (categories, name);
1039 e_cal_component_set_categories_list (comp,categories);
1040 g_slist_free (categories);
1045 is_allday = e_gw_item_get_is_allday_event (item);
1048 /* should i duplicate here ? */
1049 t = e_gw_item_get_start_date (item);
1051 itt_utc = icaltime_from_string (t);
1053 if (!is_allday && (item_type != E_GW_ITEM_TYPE_NOTE)) {
1054 if (!icaltime_get_timezone (itt_utc))
1055 icaltime_set_timezone (&itt_utc, icaltimezone_get_utc_timezone());
1057 itt = icaltime_convert_to_zone (itt_utc, default_zone);
1058 icaltime_set_timezone (&itt, default_zone);
1060 dt.tzid = icaltimezone_get_tzid (default_zone);
1062 dt.value = &itt_utc;
1063 dt.tzid = g_strdup ("UTC");
1066 dt.value = &itt_utc;
1068 dt.value->is_date = 1;
1071 e_cal_component_set_dtstart (comp, &dt);
1076 if (e_gw_item_get_recurrence_key (item) != 0) {
1078 ECalComponentRange *recur_id;
1079 char *recur_key = g_strdup_printf ("%d", e_gw_item_get_recurrence_key (item));
1081 e_cal_component_set_uid (comp, (const char *) recur_key);
1084 /* set the recurrence id and the X-GW-RECORDID too */
1085 recur_id = g_new0 (ECalComponentRange, 1);
1086 recur_id->type = E_CAL_COMPONENT_RANGE_SINGLE;
1087 recur_id->datetime = dt;
1088 e_cal_component_set_recurid (comp, recur_id);
1091 uid = e_gw_item_get_icalid (item);
1093 e_cal_component_set_uid (comp, e_gw_item_get_icalid (item));
1095 g_object_unref (comp);
1102 /* classification */
1103 description = e_gw_item_get_classification (item);
1105 if (strcmp (description, E_GW_ITEM_CLASSIFICATION_PUBLIC) == 0)
1106 e_cal_component_set_classification (comp, E_CAL_COMPONENT_CLASS_PUBLIC);
1107 else if (strcmp (description, E_GW_ITEM_CLASSIFICATION_PRIVATE) == 0)
1108 e_cal_component_set_classification (comp, E_CAL_COMPONENT_CLASS_PRIVATE);
1109 else if (strcmp (description, E_GW_ITEM_CLASSIFICATION_CONFIDENTIAL) == 0)
1110 e_cal_component_set_classification (comp, E_CAL_COMPONENT_CLASS_CONFIDENTIAL);
1112 e_cal_component_set_classification (comp, E_CAL_COMPONENT_CLASS_NONE);
1114 e_cal_component_set_classification (comp, E_CAL_COMPONENT_CLASS_NONE);
1116 if (item_type != E_GW_ITEM_TYPE_NOTE) {
1117 recipient_list = e_gw_item_get_recipient_list (item);
1118 if (recipient_list != NULL) {
1119 for (rl = recipient_list; rl != NULL; rl = rl->next) {
1120 EGwItemRecipient *recipient = (EGwItemRecipient *) rl->data;
1121 ECalComponentAttendee *attendee = g_new0 (ECalComponentAttendee, 1);
1123 attendee->cn = g_strdup (recipient->display_name);
1124 attendee->value = g_strconcat("MAILTO:", recipient->email, NULL);
1125 if (recipient->type == E_GW_ITEM_RECIPIENT_TO)
1126 attendee->role = ICAL_ROLE_REQPARTICIPANT;
1127 else if (recipient->type == E_GW_ITEM_RECIPIENT_CC || recipient->type == E_GW_ITEM_RECIPIENT_BC)
1128 attendee->role = ICAL_ROLE_OPTPARTICIPANT;
1130 attendee->role = ICAL_ROLE_NONE;
1131 /* FIXME needs a server fix on the interface
1132 * for getting cutype and the status */
1133 attendee->cutype = ICAL_CUTYPE_INDIVIDUAL;
1135 if (recipient->status == E_GW_ITEM_STAT_ACCEPTED) {
1136 const char *accept_level = e_gw_item_get_accept_level (item);
1138 if(accept_level && !strcmp (e_gw_item_get_accept_level (item),"Tentative"))
1139 attendee->status = ICAL_PARTSTAT_TENTATIVE;
1141 attendee->status = ICAL_PARTSTAT_ACCEPTED;
1143 else if (recipient->status == E_GW_ITEM_STAT_DECLINED)
1144 attendee->status = ICAL_PARTSTAT_DECLINED;
1146 attendee->status = ICAL_PARTSTAT_NEEDSACTION;
1149 attendee_list = g_slist_append (attendee_list, attendee);
1152 e_cal_component_set_attendee_list (comp, attendee_list);
1156 /* set organizer if it exists */
1157 organizer = e_gw_item_get_organizer (item);
1159 ECalComponentOrganizer *cal_organizer;
1161 cal_organizer = g_new0 (ECalComponentOrganizer, 1);
1162 cal_organizer->cn = g_strdup (organizer->display_name);
1163 cal_organizer->value = g_strconcat("MAILTO:", organizer->email, NULL);
1164 e_cal_component_set_organizer (comp, cal_organizer);
1167 /* set attachments, if any */
1168 set_attachments_to_cal_component (item, comp, cbgw);
1170 /* set specific properties */
1171 switch (item_type) {
1172 case E_GW_ITEM_TYPE_APPOINTMENT :
1174 description = e_gw_item_get_accept_level (item);
1176 (!strcmp (description, E_GW_ITEM_ACCEPT_LEVEL_BUSY) ||
1177 !strcmp (description, E_GW_ITEM_ACCEPT_LEVEL_OUT_OF_OFFICE)))
1178 e_cal_component_set_transparency (comp, E_CAL_COMPONENT_TRANSP_OPAQUE);
1180 e_cal_component_set_transparency (comp, E_CAL_COMPONENT_TRANSP_TRANSPARENT);
1183 e_cal_component_set_location (comp, e_gw_item_get_place (item));
1186 t = e_gw_item_get_end_date (item);
1188 itt_utc = icaltime_from_string (t);
1191 if (!icaltime_get_timezone (itt_utc))
1192 icaltime_set_timezone (&itt_utc, icaltimezone_get_utc_timezone());
1194 itt = icaltime_convert_to_zone (itt_utc, default_zone);
1195 icaltime_set_timezone (&itt, default_zone);
1197 dt.tzid = icaltimezone_get_tzid (default_zone);
1199 dt.value = &itt_utc;
1200 dt.tzid = g_strdup ("UTC");
1203 dt.value = &itt_utc;
1205 dt.value->is_date = 1;
1208 e_cal_component_set_dtend (comp, &dt);
1213 /* we negate the value as GW supports only "before" the start of event alarms */
1214 alarm_duration = 0 - e_gw_item_get_trigger (item);
1215 if (alarm_duration != 0) {
1216 ECalComponentAlarm *alarm;
1217 ECalComponentAlarmTrigger trigger;
1219 alarm = e_cal_component_alarm_new ();
1220 e_cal_component_alarm_set_action (alarm, E_CAL_COMPONENT_ALARM_DISPLAY);
1221 trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
1222 trigger.u.rel_duration = icaldurationtype_from_int (alarm_duration);
1223 e_cal_component_alarm_set_trigger (alarm, trigger);
1224 e_cal_component_add_alarm (comp, alarm);
1227 set_default_alarms (comp);
1230 case E_GW_ITEM_TYPE_TASK :
1232 t = e_gw_item_get_due_date (item);
1234 itt_utc = icaltime_from_string (t);
1235 if (!icaltime_get_timezone (itt_utc))
1236 icaltime_set_timezone (&itt_utc, icaltimezone_get_utc_timezone());
1238 itt = icaltime_convert_to_zone (itt_utc, default_zone);
1239 icaltime_set_timezone (&itt, default_zone);
1241 dt.tzid = icaltimezone_get_tzid (default_zone);
1243 dt.value = &itt_utc;
1244 dt.tzid = g_strdup ("UTC");
1246 e_cal_component_set_due (comp, &dt);
1249 description = e_gw_item_get_task_priority (item);
1251 if (!strcmp (description, E_GW_ITEM_PRIORITY_STANDARD))
1253 else if (!strcmp (description, E_GW_ITEM_PRIORITY_HIGH))
1260 e_cal_component_set_priority (comp, &priority);
1262 /* EGwItem's completed is a boolean */
1263 if (e_gw_item_get_completed (item)) {
1266 t = e_gw_item_get_completed_date (item);
1268 itt_utc = icaltime_from_string (t);
1269 if (!icaltime_get_timezone (itt_utc))
1270 icaltime_set_timezone (&itt_utc, icaltimezone_get_utc_timezone());
1272 itt = icaltime_convert_to_zone (itt_utc, default_zone);
1273 icaltime_set_timezone (&itt, default_zone);
1274 e_cal_component_set_completed (comp, &itt);
1276 e_cal_component_set_completed (comp, &itt_utc);
1278 /* We are setting the completion date as the current time due to
1279 the absence of completion element in the soap interface for posted
1281 itt = icaltime_today ();
1282 e_cal_component_set_completed (comp,&itt);
1286 e_cal_component_set_percent (comp, &percent);
1289 case E_GW_ITEM_TYPE_NOTE:
1295 e_cal_component_commit_sequence (comp);
1301 e_gw_connection_send_appointment (ECalBackendGroupwise *cbgw, const char *container, ECalComponent *comp, icalproperty_method method, gboolean all_instances, ECalComponent **created_comp, icalparameter_partstat *pstatus)
1304 EGwConnectionStatus status;
1305 icalparameter_partstat partstat;
1306 char *item_id = NULL;
1308 const char *recurrence_key = NULL;
1309 gboolean need_to_get = FALSE, decline = FALSE;
1310 ECalComponentVType type;
1312 cnc = e_cal_backend_groupwise_get_connection (cbgw);
1313 g_return_val_if_fail (E_IS_GW_CONNECTION (cnc), E_GW_CONNECTION_STATUS_INVALID_CONNECTION);
1314 g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), E_GW_CONNECTION_STATUS_INVALID_OBJECT);
1316 e_cal_component_commit_sequence (comp);
1317 type = e_cal_component_get_vtype (comp);
1319 gw_id = e_cal_component_get_gw_id (comp);
1323 case E_CAL_COMPONENT_EVENT:
1324 case E_CAL_COMPONENT_TODO:
1325 case E_CAL_COMPONENT_JOURNAL:
1326 if (!g_str_has_suffix (gw_id, container)) {
1327 item_id = g_strconcat (e_cal_component_get_gw_id (comp), GW_EVENT_TYPE_ID, container, NULL);
1332 item_id = g_strdup (gw_id);
1335 return E_GW_CONNECTION_STATUS_INVALID_OBJECT;
1339 e_cal_component_get_uid (comp, &recurrence_key);
1341 /*FIXME - remove this once the server returns us the same iCalid in both interfaces */
1344 EGwItem *item = NULL;
1346 status = e_gw_connection_get_item (cnc, container, item_id, "recipients message recipientStatus attachments default", &item);
1347 if (status == E_GW_CONNECTION_STATUS_OK)
1348 *created_comp = e_gw_item_to_cal_component (item, cbgw);
1350 g_object_unref (item);
1353 if (type == E_CAL_COMPONENT_JOURNAL) {
1354 icalcomponent *icalcomp = e_cal_component_get_icalcomponent (comp);
1355 icalproperty *icalprop;
1357 icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
1361 x_name = icalproperty_get_x_name (icalprop);
1362 if (!strcmp (x_name, "X-GW-DECLINED")) {
1364 *pstatus = ICAL_PARTSTAT_DECLINED;
1367 icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
1372 case ICAL_METHOD_REQUEST:
1373 /* get attendee here and add the list along. */
1374 if (e_cal_component_has_attendees (comp)) {
1375 GSList *attendee_list, *l;
1376 const char *email_id;
1377 ECalComponentAttendee *attendee = NULL, *tmp;
1380 e_cal_component_get_attendee_list (comp, &attendee_list);
1381 for (l = attendee_list; l ; l = g_slist_next (l)) {
1382 tmp = (ECalComponentAttendee *) (l->data);
1383 email_id = tmp->value;
1385 if (!g_ascii_strncasecmp (email_id, "mailto:", 7))
1388 if (!g_ascii_strcasecmp (email_id, e_gw_connection_get_user_email (cnc))) {
1394 partstat = attendee->status;
1397 status = E_GW_CONNECTION_STATUS_INVALID_OBJECT;
1401 e_cal_component_free_attendee_list (attendee_list);
1405 status = E_GW_CONNECTION_STATUS_INVALID_OBJECT;
1408 *pstatus = partstat;
1410 ECalComponentTransparency transp;
1412 case ICAL_PARTSTAT_ACCEPTED:
1413 e_cal_component_get_transparency (comp, &transp);
1414 if (transp == E_CAL_COMPONENT_TRANSP_OPAQUE) {
1416 status = e_gw_connection_accept_request (cnc, item_id, "Busy", NULL, recurrence_key);
1418 status = e_gw_connection_accept_request (cnc, item_id, "Busy", NULL, NULL);
1422 status = e_gw_connection_accept_request (cnc, item_id, "Free", NULL, recurrence_key);
1424 status = e_gw_connection_accept_request (cnc, item_id, "Free", NULL, NULL);
1427 case ICAL_PARTSTAT_DECLINED:
1429 status = e_gw_connection_decline_request (cnc, item_id, NULL, recurrence_key);
1431 status = e_gw_connection_decline_request (cnc, item_id, NULL, NULL);
1434 case ICAL_PARTSTAT_TENTATIVE:
1436 status = e_gw_connection_accept_request (cnc, item_id, "Tentative", NULL, recurrence_key);
1438 status = e_gw_connection_accept_request (cnc, item_id, "Tentative", NULL, NULL);
1440 case ICAL_PARTSTAT_COMPLETED:
1441 status = e_gw_connection_complete_request (cnc, item_id);
1444 status = E_GW_CONNECTION_STATUS_INVALID_OBJECT;
1450 case ICAL_METHOD_CANCEL:
1451 status = e_gw_connection_retract_request (cnc, item_id, NULL, FALSE, FALSE);
1453 case ICAL_METHOD_PUBLISH:
1455 status = e_gw_connection_decline_request (cnc, item_id, NULL, NULL);
1457 status = e_gw_connection_accept_request (cnc, item_id, "Free", NULL, NULL);
1460 return E_GW_CONNECTION_STATUS_INVALID_OBJECT;
1467 e_gw_connection_create_appointment (EGwConnection *cnc, const char *container, ECalBackendGroupwise *cbgw, ECalComponent *comp, GSList **id_list)
1470 EGwConnectionStatus status;
1471 icalproperty *icalprop;
1472 gboolean move_cal = FALSE;
1473 icalcomponent *icalcomp;
1476 g_return_val_if_fail (E_IS_GW_CONNECTION (cnc), E_GW_CONNECTION_STATUS_INVALID_CONNECTION);
1477 g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), E_GW_CONNECTION_STATUS_INVALID_OBJECT);
1479 icalcomp = e_cal_component_get_icalcomponent (comp);
1481 icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
1485 x_name = icalproperty_get_x_name (icalprop);
1486 if (!strcmp (x_name, "X-EVOLUTION-MOVE-CALENDAR")) {
1491 icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
1494 item = e_gw_item_new_from_cal_component (container, cbgw, comp);
1495 e_gw_item_set_container_id (item, container);
1497 status = e_gw_connection_send_item (cnc, item, id_list);
1499 e_gw_item_set_source (item, "personal");
1500 status = e_gw_connection_create_item (cnc, item, &id);
1501 *id_list = g_slist_append (*id_list, id);
1503 g_object_unref (item);
1508 static EGwConnectionStatus
1509 start_freebusy_session (EGwConnection *cnc, GList *users,
1510 time_t start, time_t end, const char **session)
1512 SoupSoapMessage *msg;
1513 SoupSoapResponse *response;
1514 EGwConnectionStatus status;
1515 SoupSoapParameter *param;
1517 icaltimetype icaltime;
1519 const char *start_date, *end_date;
1522 return E_GW_CONNECTION_STATUS_INVALID_OBJECT;
1524 /* build the SOAP message */
1525 msg = e_gw_message_new_with_header (e_gw_connection_get_uri (cnc),
1526 e_gw_connection_get_session_id (cnc),
1527 "startFreeBusySessionRequest");
1528 /* FIXME users is just a buch of user names - associate it with uid,
1529 * email id apart from the name*/
1531 soup_soap_message_start_element (msg, "users", NULL, NULL);
1532 for ( l = users; l != NULL; l = g_list_next (l)) {
1533 soup_soap_message_start_element (msg, "user", NULL, NULL);
1534 e_gw_message_write_string_parameter (msg, "email", NULL, l->data);
1535 soup_soap_message_end_element (msg);
1538 soup_soap_message_end_element (msg);
1541 utc = icaltimezone_get_utc_timezone ();
1542 icaltime = icaltime_from_timet_with_zone (start, FALSE, utc);
1543 start_date = icaltime_as_ical_string (icaltime);
1545 icaltime = icaltime_from_timet_with_zone (end, FALSE, utc);
1546 end_date = icaltime_as_ical_string (icaltime);
1548 e_gw_message_write_string_parameter (msg, "startDate", NULL, start_date);
1549 e_gw_message_write_string_parameter (msg, "endDate", NULL, end_date);
1551 e_gw_message_write_footer (msg);
1553 /* send message to server */
1554 response = e_gw_connection_send_message (cnc, msg);
1556 g_object_unref (msg);
1557 return E_GW_CONNECTION_STATUS_NO_RESPONSE;
1560 status = e_gw_connection_parse_response_status (response);
1561 if (status != E_GW_CONNECTION_STATUS_OK)
1563 g_object_unref (msg);
1564 g_object_unref (response);
1568 /* if status is OK - parse result, return the list */
1569 param = soup_soap_response_get_first_parameter_by_name (response, "freeBusySessionId");
1571 g_object_unref (response);
1572 g_object_unref (msg);
1573 return E_GW_CONNECTION_STATUS_INVALID_RESPONSE;
1576 *session = soup_soap_parameter_get_string_value (param);
1578 g_object_unref (response);
1579 g_object_unref (msg);
1584 static EGwConnectionStatus
1585 close_freebusy_session (EGwConnection *cnc, const char *session)
1587 SoupSoapMessage *msg;
1588 SoupSoapResponse *response;
1589 EGwConnectionStatus status;
1591 /* build the SOAP message */
1592 msg = e_gw_message_new_with_header (e_gw_connection_get_uri (cnc),
1593 e_gw_connection_get_session_id (cnc),
1594 "closeFreeBusySessionRequest");
1595 e_gw_message_write_string_parameter (msg, "freeBusySessionId", NULL, session);
1596 e_gw_message_write_footer (msg);
1598 /* send message to server */
1599 response = e_gw_connection_send_message (cnc, msg);
1601 g_object_unref (msg);
1602 return E_GW_CONNECTION_STATUS_NO_RESPONSE;
1605 status = e_gw_connection_parse_response_status (response);
1607 g_object_unref (msg);
1608 g_object_unref (response);
1613 e_gw_connection_get_freebusy_info (EGwConnection *cnc, GList *users, time_t start, time_t end, GList **freebusy, icaltimezone *default_zone)
1615 SoupSoapMessage *msg;
1616 SoupSoapResponse *response;
1617 EGwConnectionStatus status;
1618 SoupSoapParameter *param, *subparam, *param_outstanding;
1619 const char *session, *outstanding = NULL;
1620 gboolean resend_request = TRUE;
1621 int request_iteration = 0;
1623 g_return_val_if_fail (E_IS_GW_CONNECTION (cnc), E_GW_CONNECTION_STATUS_INVALID_CONNECTION);
1625 /* Perform startFreeBusySession */
1626 status = start_freebusy_session (cnc, users, start, end, &session);
1627 /*FIXME log error messages */
1628 if (status != E_GW_CONNECTION_STATUS_OK)
1632 while (resend_request) {
1635 /* build the SOAP message */
1636 msg = e_gw_message_new_with_header (e_gw_connection_get_uri (cnc),
1637 e_gw_connection_get_session_id (cnc),
1638 "getFreeBusyRequest");
1639 e_gw_message_write_string_parameter (msg, "freeBusySessionId", NULL, session);
1640 e_gw_message_write_footer (msg);
1642 /* send message to server */
1643 response = e_gw_connection_send_message (cnc, msg);
1645 g_object_unref (msg);
1646 return E_GW_CONNECTION_STATUS_NO_RESPONSE;
1649 status = e_gw_connection_parse_response_status (response);
1650 if (status != E_GW_CONNECTION_STATUS_OK) {
1651 g_object_unref (msg);
1652 g_object_unref (response);
1656 param = soup_soap_response_get_first_parameter_by_name (response, "freeBusyStats");
1658 g_object_unref (response);
1659 g_object_unref (msg);
1660 return E_GW_CONNECTION_STATUS_INVALID_RESPONSE;
1663 param_outstanding = soup_soap_parameter_get_first_child_by_name (param, "outstanding");
1664 if (param_outstanding)
1665 outstanding = soup_soap_parameter_get_string_value (param_outstanding);
1666 /* Try 12 times - this is approximately 2 minutes of time to
1667 * obtain the free/busy information from the server */
1668 if (outstanding && strcmp (outstanding, "0") && (request_iteration < 12)) {
1669 request_iteration++;
1670 g_object_unref (msg);
1671 g_object_unref (response);
1672 g_usleep (10000000);
1676 /* FIXME the FreeBusyStats are not used currently. */
1677 param = soup_soap_response_get_first_parameter_by_name (response, "freeBusyInfo");
1679 g_object_unref (response);
1680 g_object_unref (msg);
1681 return E_GW_CONNECTION_STATUS_INVALID_RESPONSE;
1684 resend_request = FALSE;
1686 for (subparam = soup_soap_parameter_get_first_child_by_name (param, "user");
1688 subparam = soup_soap_parameter_get_next_child_by_name (subparam, "user")) {
1689 SoupSoapParameter *param_blocks, *subparam_block, *tmp;
1690 const char *uuid = NULL, *email = NULL, *name = NULL;
1691 ECalComponent *comp;
1692 ECalComponentAttendee attendee;
1693 GSList *attendee_list = NULL;
1694 icalcomponent *icalcomp = NULL;
1696 tmp = soup_soap_parameter_get_first_child_by_name (subparam, "email");
1698 email = soup_soap_parameter_get_string_value (tmp);
1699 tmp = soup_soap_parameter_get_first_child_by_name (subparam, "uuid");
1701 uuid = soup_soap_parameter_get_string_value (tmp);
1702 tmp = soup_soap_parameter_get_first_child_by_name (subparam, "displayName");
1704 name = soup_soap_parameter_get_string_value (tmp);
1706 comp = e_cal_component_new ();
1707 e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_FREEBUSY);
1708 e_cal_component_commit_sequence (comp);
1709 icalcomp = e_cal_component_get_icalcomponent (comp);
1711 memset (&attendee, 0, sizeof (ECalComponentAttendee));
1715 attendee.value = email;
1717 attendee.cutype = ICAL_CUTYPE_INDIVIDUAL;
1718 attendee.role = ICAL_ROLE_REQPARTICIPANT;
1719 attendee.status = ICAL_PARTSTAT_NEEDSACTION;
1721 /* XXX the uuid is not currently used. hence it is
1724 attendee_list = g_slist_append (attendee_list, &attendee);
1726 e_cal_component_set_attendee_list (comp, attendee_list);
1729 param_blocks = soup_soap_parameter_get_first_child_by_name (subparam, "blocks");
1730 if (!param_blocks) {
1731 g_object_unref (response);
1732 g_object_unref (msg);
1733 return E_GW_CONNECTION_STATUS_INVALID_RESPONSE;
1736 for (subparam_block = soup_soap_parameter_get_first_child_by_name (param_blocks, "block");
1737 subparam_block != NULL;
1738 subparam_block = soup_soap_parameter_get_next_child_by_name (subparam_block, "block")) {
1740 /* process each block and create ECal free/busy components.*/
1741 SoupSoapParameter *tmp;
1742 struct icalperiodtype ipt;
1743 icalproperty *icalprop;
1746 const char *start, *end, *accept_level;
1748 memset (&ipt, 0, sizeof (struct icalperiodtype));
1749 tmp = soup_soap_parameter_get_first_child_by_name (subparam_block, "startDate");
1751 start = soup_soap_parameter_get_string_value (tmp);
1752 t = e_gw_connection_get_date_from_string (start);
1753 itt = icaltime_from_timet_with_zone (t, 0, default_zone ? default_zone : NULL);
1757 tmp = soup_soap_parameter_get_first_child_by_name (subparam_block, "endDate");
1759 end = soup_soap_parameter_get_string_value (tmp);
1760 t = e_gw_connection_get_date_from_string (end);
1761 itt = icaltime_from_timet_with_zone (t, 0, default_zone ? default_zone : NULL);
1764 icalprop = icalproperty_new_freebusy (ipt);
1766 tmp = soup_soap_parameter_get_first_child_by_name (subparam_block, "acceptLevel");
1768 accept_level = soup_soap_parameter_get_string_value (tmp);
1769 if (!strcmp (accept_level, "Busy"))
1770 icalproperty_set_parameter_from_string (icalprop, "FBTYPE", "BUSY");
1771 else if (!strcmp (accept_level, "Tentative"))
1772 icalproperty_set_parameter_from_string (icalprop, "FBTYPE", "BUSYTENTATIVE");
1773 else if (!strcmp (accept_level, "OutOfOffice"))
1774 icalproperty_set_parameter_from_string (icalprop, "FBTYPE", "BUSYUNAVAILABLE");
1775 else if (!strcmp (accept_level, "Free"))
1776 icalproperty_set_parameter_from_string (icalprop, "FBTYPE", "FREE");
1778 icalcomponent_add_property(icalcomp, icalprop);
1782 e_cal_component_commit_sequence (comp);
1783 *freebusy = g_list_append (*freebusy, e_cal_component_get_as_string (comp));
1784 g_object_unref (comp);
1787 g_object_unref (msg);
1788 g_object_unref (response);
1790 } /* end of while loop */
1792 /* closeFreeBusySession*/
1793 return close_freebusy_session (cnc, session);
1796 #define SET_DELTA(fieldname) G_STMT_START{ \
1797 fieldname = e_gw_item_get_##fieldname (item); \
1798 cache_##fieldname = e_gw_item_get_##fieldname (cache_item); \
1799 if ( cache_##fieldname ) { \
1801 e_gw_item_set_change (item, E_GW_ITEM_CHANGE_TYPE_DELETE, #fieldname, (gpointer) cache_##fieldname );\
1802 else if (strcmp ( fieldname, cache_##fieldname )) \
1803 e_gw_item_set_change (item, E_GW_ITEM_CHANGE_TYPE_UPDATE, #fieldname, (gpointer) fieldname );\
1805 else if ( fieldname ) \
1806 e_gw_item_set_change (item, E_GW_ITEM_CHANGE_TYPE_ADD, #fieldname, (gpointer) fieldname ); \
1810 set_categories_changes (EGwItem *new_item, EGwItem *old_item)
1812 GList *old_category_list;
1813 GList *new_category_list;
1814 GList *temp, *old_categories_copy, *added_categories = NULL;
1815 gboolean categories_matched;
1816 char *category1, *category2;
1817 old_category_list = e_gw_item_get_categories (old_item);
1818 new_category_list = e_gw_item_get_categories (new_item);
1819 if (old_category_list && new_category_list) {
1820 old_categories_copy = g_list_copy (old_category_list);
1821 for ( ; new_category_list != NULL; new_category_list = g_list_next (new_category_list)) {
1823 category1 = new_category_list->data;
1824 temp = old_category_list;
1825 categories_matched = FALSE;
1826 for(; temp != NULL; temp = g_list_next (temp)) {
1827 category2 = temp->data;
1828 if ( g_str_equal (category1, category2)) {
1829 categories_matched = TRUE;
1830 old_categories_copy = g_list_remove (old_categories_copy, category2);
1835 if (!categories_matched)
1836 added_categories = g_list_append (added_categories, category1);
1839 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, "categories", added_categories);
1840 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, "categories", old_categories_copy);
1842 } else if (!new_category_list && old_category_list) {
1843 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_DELETE, "categories", old_category_list);
1844 } else if (new_category_list && !old_category_list) {
1845 e_gw_item_set_change (new_item, E_GW_ITEM_CHANGE_TYPE_ADD, "categories", new_category_list);
1851 e_gw_item_set_changes (EGwItem *item, EGwItem *cache_item)
1853 const char *subject, *cache_subject;
1854 const char *message, *cache_message;
1855 const char *classification, *cache_classification;
1856 const char *accept_level, *cache_accept_level;
1857 const char *place, *cache_place;
1858 const char *task_priority, *cache_task_priority;
1859 int trigger, cache_trigger;
1860 char *due_date, *cache_due_date;
1861 char *start_date, *cache_start_date;
1862 char *end_date, *cache_end_date;
1863 gboolean is_allday, cache_is_allday;
1865 /* TODO assert the types of the items are the same */
1869 SET_DELTA(classification);
1872 SET_DELTA(start_date);
1873 set_categories_changes (item, cache_item);
1874 /*FIXME recipient_list modifications need go here after server starts
1875 * supporting retraction */
1876 if (e_gw_item_get_item_type (item) == E_GW_ITEM_TYPE_APPOINTMENT) {
1878 SET_DELTA(end_date);
1879 SET_DELTA(accept_level);
1881 trigger = e_gw_item_get_trigger (item);
1882 cache_trigger = e_gw_item_get_trigger (cache_item);
1883 if (cache_trigger) {
1885 e_gw_item_set_change (item, E_GW_ITEM_CHANGE_TYPE_DELETE, "alarm", &cache_trigger);
1886 else if (trigger != cache_trigger)
1887 e_gw_item_set_change (item, E_GW_ITEM_CHANGE_TYPE_UPDATE, "alarm", &trigger);
1890 e_gw_item_set_change (item, E_GW_ITEM_CHANGE_TYPE_ADD, "alarm", &trigger);
1891 is_allday = e_gw_item_get_is_allday_event (item);
1892 cache_is_allday = e_gw_item_get_is_allday_event (cache_item);
1894 if ((is_allday && !cache_is_allday) || (!is_allday && cache_is_allday))
1895 e_gw_item_set_change (item, E_GW_ITEM_CHANGE_TYPE_UPDATE, "allDayEvent", &is_allday);
1897 else if ( e_gw_item_get_item_type (item) == E_GW_ITEM_TYPE_TASK) {
1898 SET_DELTA(due_date);
1899 SET_DELTA(task_priority);
1905 add_return_value (EGwSendOptionsReturnNotify track, ESource *source, char *notify)
1910 case E_GW_RETURN_NOTIFY_MAIL:
1911 value = g_strdup ("mail");
1914 value = g_strdup ("none");
1917 e_source_set_property (source, notify, value);
1918 g_free (value), value = NULL;
1922 e_cal_backend_groupwise_store_settings (GwSettings *hold)
1924 ECalBackendGroupwise *cbgw;
1925 EGwSendOptions *opts;
1926 EGwSendOptionsGeneral *gopts;
1927 EGwSendOptionsStatusTracking *sopts;
1929 icalcomponent_kind kind;
1930 GConfClient *gconf = gconf_client_get_default ();
1932 ESourceList *source_list;
1938 source = e_cal_backend_get_source (E_CAL_BACKEND (cbgw));
1939 kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbgw));
1941 /* TODO implement send options for Notes */
1942 if (kind == ICAL_VJOURNAL_COMPONENT)
1945 gopts = e_gw_sendoptions_get_general_options (opts);
1946 if (kind == ICAL_VEVENT_COMPONENT) {
1947 source_list = e_source_list_new_for_gconf (gconf, "/apps/evolution/calendar/sources");
1948 sopts = e_gw_sendoptions_get_status_tracking_options (opts, "calendar");
1950 source_list = e_source_list_new_for_gconf (gconf, "/apps/evolution/tasks/sources");
1951 sopts = e_gw_sendoptions_get_status_tracking_options (opts, "task");
1954 uid = e_source_peek_uid (source);
1955 source = e_source_list_peek_source_by_uid (source_list, uid);
1958 switch (gopts->priority) {
1959 case E_GW_PRIORITY_HIGH:
1960 value = g_strdup ("high");
1962 case E_GW_PRIORITY_STANDARD:
1963 value = g_strdup ("standard");
1965 case E_GW_PRIORITY_LOW:
1966 value = g_strdup ("low");
1969 value = g_strdup ("undefined");
1971 e_source_set_property (source, "priority", value);
1972 g_free (value), value = NULL;
1974 /* Reply Requested */
1975 if (gopts->reply_enabled) {
1976 if (gopts->reply_convenient)
1977 value = g_strdup ("convinient");
1979 value = g_strdup_printf ("%d",gopts->reply_within);
1981 value = g_strdup ("none");
1982 e_source_set_property (source, "reply-requested", value);
1983 g_free (value), value = NULL;
1985 /* Delay delivery */
1986 if (gopts->delay_enabled) {
1988 tt = icaltime_today ();
1989 icaltime_adjust (&tt, gopts->delay_until, 0, 0, 0);
1990 value = icaltime_as_ical_string (tt);
1992 value = g_strdup ("none");
1993 e_source_set_property (source, "delay-delivery", value);
1994 g_free (value), value = NULL;
1996 /* Expiration date */
1997 if (gopts->expiration_enabled)
1998 value = g_strdup_printf ("%d", gopts->expire_after);
2000 value = g_strdup ("none");
2001 e_source_set_property (source, "expiration", value);
2002 g_free (value), value = NULL;
2006 /* status tracking */
2007 if (sopts->tracking_enabled) {
2008 switch (sopts->track_when) {
2009 case E_GW_DELIVERED :
2010 value = g_strdup ("delivered");
2012 case E_GW_DELIVERED_OPENED:
2013 value = g_strdup ("delivered-opened");
2016 value = g_strdup ("all");
2019 value = g_strdup ("none");
2020 e_source_set_property (source, "status-tracking", value);
2021 g_free (value), value = NULL;
2023 add_return_value (sopts->opened, source, "return-open");
2024 add_return_value (sopts->accepted, source, "return-accept");
2025 add_return_value (sopts->declined, source, "return-decline");
2026 add_return_value (sopts->completed, source, "return-complete");
2029 e_source_list_sync (source_list, NULL);
2031 g_object_unref (hold->opts);
2034 g_object_unref (gconf);
2035 g_object_unref (source_list);
2041 e_cal_backend_groupwise_utils_check_delegate (ECalComponent *comp, const char *email)
2044 icalcomponent *icalcomp = e_cal_component_get_icalcomponent (comp);
2046 /*TODO remove the argument email */
2047 prop = icalcomponent_get_first_property (icalcomp,
2050 const char *x_name, *x_val;
2052 x_name = icalproperty_get_x_name (prop);
2053 x_val = icalproperty_get_x (prop);
2054 if (!strcmp (x_name, "X-EVOLUTION-DELEGATED")) {
2055 icalcomponent_remove_property (icalcomp, prop);
2059 prop = icalcomponent_get_next_property (e_cal_component_get_icalcomponent (comp),