/* cal-backend-wcap-tasks.c * * Copyright (C) 2002-2004 Sun Microsystems, Inc * * AUTHORS * Jack Jia * Harry Lu * Alfred Peng * Jedy Wang * Rodrigo Moya * JP Rosevear * */ #ifdef HAVE_CONFIG_H #include #endif #include #include "lib/sunone-util.h" #include "cal-backend-wcap-tasks.h" static CalBackendWCAPClass *parent_class = NULL; #define d(x) G_DEFINE_TYPE (CalBackendWCAPTasks, cal_backend_wcap_tasks, CAL_BACKEND_WCAP_TYPE) static void process_tasks_component_to_server (CalBackendWCAP *wcap, ECalComponent *comp, gboolean *relativeAlarm, gboolean *allday) { ECalComponentDateTime dt,dtstart; icalcomponent *icalcomp; icalproperty *prop; icaltimezone *zone = NULL, *old_zone = NULL; char *location = NULL; /* Every task has a start time */ e_cal_component_get_dtstart (comp, &dt); if (!dt.value) { dt.value = g_new0 (struct icaltimetype, 1); *dt.value = icaltime_from_timet_with_zone (time (NULL), FALSE, cal_backend_wcap_get_default_zone (wcap)); dt.tzid = g_strdup (icaltimezone_get_tzid (cal_backend_wcap_get_default_zone (wcap))); e_cal_component_set_dtstart (comp, &dt); } e_cal_component_free_datetime (&dt); /* Ok, Sunone can't handle other timezones, so, we make a * guess as to the timezone intended, if we fail, we convert * it to the default server side timezone for this calendar */ e_cal_component_get_dtstart (comp, &dtstart); if (dtstart.value && dtstart.tzid) { zone = cal_backend_wcap_get_timezone_from_tzid (wcap, dtstart.tzid, TRUE); if (!zone) { zone = icaltimezone_get_builtin_timezone_from_tzid (dtstart.tzid); if (zone) { icaltimezone *local_zone; location = icaltimezone_get_location (zone); local_zone = cal_backend_wcap_get_timezone_from_tzid (wcap, location, TRUE); if (!local_zone) local_zone = cal_backend_wcap_get_server_default_zone (wcap); icaltimezone_convert_time (dtstart.value, zone, local_zone); g_free ((char *)dtstart.tzid); dtstart.tzid = g_strdup (icaltimezone_get_tzid (local_zone)); e_cal_component_set_dtstart (comp, &dtstart); zone = local_zone; } } } e_cal_component_free_datetime (&dtstart); if (zone) location = icaltimezone_get_tzid (zone); /* Convert other Date-Time values to the same zone as the start time */ if (zone) { e_cal_component_get_dtend (comp, &dt); if (dt.value && dt.tzid) { old_zone = e_cal_backend_internal_get_timezone (E_CAL_BACKEND (wcap), dt.tzid); icaltimezone_convert_time (dt.value, old_zone, zone); g_free ((char *)dt.tzid); dt.tzid = g_strdup (icaltimezone_get_tzid (zone)); e_cal_component_set_dtend (comp, &dt); } e_cal_component_free_datetime (&dt); } if (zone) { e_cal_component_get_due (comp, &dt); if (dt.value && dt.tzid) { old_zone = e_cal_backend_internal_get_timezone (E_CAL_BACKEND (wcap), dt.tzid); icaltimezone_convert_time (dt.value, old_zone, zone); g_free ((char *)dt.tzid); dt.tzid = g_strdup (icaltimezone_get_tzid (zone)); e_cal_component_set_due (comp, &dt); } e_cal_component_free_datetime (&dt); } e_cal_component_abort_sequence (comp); /* Set x properties */ icalcomp = e_cal_component_get_icalcomponent (comp); prop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY); while (prop) { const char *x_name, *x_val; x_name = icalproperty_get_x_name (prop); x_val = icalproperty_get_x (prop); if (!strcmp (x_name, "X-NSCP-DTSTART-TZID") && location) { icalproperty_set_x (prop, location); location = NULL; } prop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY); } if (location) { prop = icalproperty_new_x (location); icalproperty_set_x_name (prop, "X-NSCP-DTSTART-TZID"); icalcomponent_add_property (icalcomp, prop); } e_cal_component_abort_sequence (comp); } static ECalBackendSyncStatus cal_backend_wcap_tasks_update_objects (ECalBackendSync *backend, EDataCal *cal, const char *calobj, CalObjModType mod, char **old_object) { ECalBackendSyncStatus result = GNOME_Evolution_Calendar_Success; CalBackendWCAP *wcap = CAL_BACKEND_WCAP (backend); ECalComponent *comp; icalcomponent *toplevel_comp, *subcomp; icalcomponent_kind kind; gboolean hasImport = FALSE; gboolean relativeAlarm = FALSE; g_return_val_if_fail (IS_CAL_BACKEND_WCAP (wcap), GNOME_Evolution_Calendar_OtherError); if (!cal_backend_wcap_is_online (wcap)) return GNOME_Evolution_Calendar_RepositoryOffline; if (!cal_backend_wcap_get_connection (wcap)) return cal_backend_wcap_get_open_error (wcap); toplevel_comp = icalparser_parse_string (calobj); if (!toplevel_comp) return GNOME_Evolution_Calendar_InvalidObject; kind = icalcomponent_isa (toplevel_comp); if (kind == ICAL_VTODO_COMPONENT) { icalcomponent *icalcomp; /* Create a temporary toplevel component and put VTODO in it, to simplify the code below. */ icalcomp = toplevel_comp; toplevel_comp = e_cal_util_new_top_level (); icalcomponent_add_component (toplevel_comp, icalcomp); } else if (kind != ICAL_VCALENDAR_COMPONENT) { /* We don't support this type of component */ icalcomponent_free (toplevel_comp); return GNOME_Evolution_Calendar_InvalidObject; } subcomp = icalcomponent_get_first_component (toplevel_comp, ICAL_ANY_COMPONENT); comp = e_cal_component_new (); while (subcomp) { /* We ignore anything except VTODO and VJOURNAL components. */ icalcomponent_kind child_kind = icalcomponent_isa (subcomp); if (child_kind == ICAL_VTODO_COMPONENT) { icalcomponent *return_icalcomp, *return_subcomp; const char *uid; gboolean allday = FALSE, expand = FALSE; guint error_code; SunOneMethod method; e_cal_component_set_icalcomponent (comp, subcomp); /* Fix up the component for the server */ process_tasks_component_to_server (wcap, comp, &relativeAlarm, &allday); if (cal_backend_wcap_need_import (wcap, comp)) { result = cal_backend_wcap_handle_import (wcap, comp, mod, toplevel_comp, subcomp, child_kind); subcomp = icalcomponent_get_next_component (toplevel_comp, ICAL_ANY_COMPONENT); hasImport = TRUE; continue; } /* Get the uid for verification */ e_cal_component_get_uid (comp, &uid); /* Guess the method */ method = cal_backend_wcap_guess_method (wcap, cal, comp); error_code = sunone_connection_storetodos (cal_backend_wcap_get_connection (wcap), cal_backend_wcap_get_calid (wcap), subcomp, method, cal_backend_wcap_to_sunone_mod (mod, comp), expand, allday, &return_icalcomp, cal_backend_wcap_get_account_email (wcap)); cal_backend_wcap_verify_exists_uid (wcap, uid); e_cal_component_set_icalcomponent (comp, NULL); if (!SUNONE_ERROR_IS_SUCCESSFUL (error_code)) { result = cal_backend_wcap_result_from_error (error_code); subcomp = icalcomponent_get_next_component (toplevel_comp, ICAL_ANY_COMPONENT); continue; } return_subcomp = icalcomponent_get_first_component (return_icalcomp, child_kind); while (return_subcomp) { cal_backend_wcap_add_component (wcap, return_subcomp, TRUE, old_object, NULL); return_subcomp = icalcomponent_get_next_component (return_icalcomp, child_kind); } icalcomponent_free (return_icalcomp); } subcomp = icalcomponent_get_next_component (toplevel_comp, ICAL_ANY_COMPONENT); } g_object_unref (G_OBJECT (comp)); icalcomponent_free (toplevel_comp); if (hasImport || relativeAlarm) cal_backend_wcap_poll_cb (wcap); else cal_backend_wcap_write_cache (wcap); return result; } static ECalBackendSyncStatus cal_backend_wcap_tasks_create_object (ECalBackendSync *backend, EDataCal *cal, char **calobj, char **uid) { ECalBackendSyncStatus result = GNOME_Evolution_Calendar_Success; CalObjModType mod = CALOBJ_MOD_ALL; g_return_val_if_fail (calobj != NULL, GNOME_Evolution_Calendar_InvalidObject); d(printf("cal_backend_wcap_tasks_create_object(%p, %s)\n", backend, *calobj)); result = cal_backend_wcap_tasks_update_objects (backend, cal, *calobj, mod, NULL); /* *calobj = NULL; */ return result; } static ECalBackendSyncStatus cal_backend_wcap_tasks_modify_object (ECalBackendSync *backend, EDataCal *cal, const char *calobj, CalObjModType mod, char **old_object, char **new_object) { ECalBackendSyncStatus result = GNOME_Evolution_Calendar_Success; g_return_val_if_fail (calobj != NULL, GNOME_Evolution_Calendar_InvalidObject); d(printf("cal_backend_wcap_tasks_modify_object(%p, %s)\n", backend, calobj)); result = cal_backend_wcap_tasks_update_objects (backend, cal, calobj, mod, old_object); return result; } static ECalBackendSyncStatus cal_backend_wcap_tasks_remove_object (ECalBackendSync *backend, EDataCal *cal, const char *uid, const char *rid, CalObjModType mod, char **old_object, char **object) { CalBackendWCAP *wcap = CAL_BACKEND_WCAP (backend); ECalComponent *comp; icalcomponent *icalcomp; ECalBackendSyncStatus status; guint error_code; char *calobj; d(printf("cal_backend_wcap_tasks_remove_object(%p, %s, %s)\n", backend, uid, rid)); if (!cal_backend_wcap_is_online (wcap)) return GNOME_Evolution_Calendar_RepositoryOffline; if (!cal_backend_wcap_get_connection (wcap)) return cal_backend_wcap_get_open_error (wcap); status = E_CAL_BACKEND_SYNC_CLASS (parent_class)->get_object_sync (backend, cal, uid, rid, &calobj); if (status != GNOME_Evolution_Calendar_Success) return status; icalcomp = icalcomponent_new_from_string (calobj); if (!icalcomp) { g_free (calobj); return GNOME_Evolution_Calendar_InvalidObject; } comp = e_cal_component_new (); e_cal_component_set_icalcomponent (comp, icalcomp); e_cal_component_get_uid (comp, &uid); rid = cal_backend_wcap_get_rid_string (comp); error_code = sunone_connection_deletetodos_by_id (cal_backend_wcap_get_connection (wcap), cal_backend_wcap_get_calid (wcap), uid, rid, cal_backend_wcap_to_sunone_mod (mod, comp)); if (!SUNONE_ERROR_IS_SUCCESSFUL (error_code)) { g_object_unref (G_OBJECT (comp)); g_free (calobj); return cal_backend_wcap_result_from_error (error_code); } cal_backend_wcap_remove_component (wcap, uid, mod, old_object); g_object_unref (G_OBJECT (comp)); g_free (calobj); cal_backend_wcap_write_cache (wcap); return GNOME_Evolution_Calendar_Success; } static ECalBackendSyncStatus cal_backend_wcap_tasks_receive_objects (ECalBackendSync *backend, EDataCal *cal, const char *calobj) { ECalBackendSyncStatus result = GNOME_Evolution_Calendar_Success; CalBackendWCAP *wcap = CAL_BACKEND_WCAP (backend); icalcomponent *toplevel_comp; icalcomponent_kind kind; guint error_code; g_return_val_if_fail (calobj != NULL, GNOME_Evolution_Calendar_InvalidObject); d(printf("cal_backend_wcap_tasks_receive_objects(%p, %p, %s)\n", backend, cal, calobj)); g_return_val_if_fail (IS_CAL_BACKEND_WCAP (wcap), GNOME_Evolution_Calendar_OtherError); if (!cal_backend_wcap_is_online (wcap)) return GNOME_Evolution_Calendar_RepositoryOffline; if (!cal_backend_wcap_get_connection (wcap)) return cal_backend_wcap_get_open_error (wcap); toplevel_comp = icalparser_parse_string (calobj); if (!toplevel_comp) return GNOME_Evolution_Calendar_InvalidObject; kind = icalcomponent_isa (toplevel_comp); if (kind == ICAL_VTODO_COMPONENT) { icalcomponent *icalcomp; /* Create a temporary toplevel component and put VTODO in it, to simplify the code below. */ icalcomp = toplevel_comp; toplevel_comp = e_cal_util_new_top_level (); icalcomponent_add_component (toplevel_comp, icalcomp); } else if (kind != ICAL_VCALENDAR_COMPONENT) { /* We don't support this type of component */ icalcomponent_free (toplevel_comp); return GNOME_Evolution_Calendar_InvalidObject; } error_code = sunone_connection_import (cal_backend_wcap_get_connection (wcap), cal_backend_wcap_get_calid (wcap), toplevel_comp); if (!SUNONE_ERROR_IS_SUCCESSFUL (error_code)) result = cal_backend_wcap_result_from_error (error_code); cal_backend_wcap_poll_cb (wcap); icalcomponent_free (toplevel_comp); return result; } static void e_cal_backend_wcap_tasks_dispose(GObject *object) { if (G_OBJECT_CLASS (parent_class)->dispose) (*G_OBJECT_CLASS (parent_class)->dispose) (object); } static void e_cal_backend_wcap_tasks_finalize(GObject *object) { if (G_OBJECT_CLASS (parent_class)->finalize) (*G_OBJECT_CLASS (parent_class)->finalize) (object); } static void cal_backend_wcap_tasks_class_init (CalBackendWCAPTasksClass *klass) { GObjectClass *object_class; ECalBackendClass *backend_class; ECalBackendSyncClass *sync_class; object_class = G_OBJECT_CLASS (klass); backend_class = E_CAL_BACKEND_CLASS (klass); sync_class = E_CAL_BACKEND_SYNC_CLASS (klass); parent_class = g_type_class_peek_parent (klass); sync_class->create_object_sync = cal_backend_wcap_tasks_create_object; sync_class->modify_object_sync = cal_backend_wcap_tasks_modify_object; sync_class->remove_object_sync = cal_backend_wcap_tasks_remove_object; sync_class->receive_objects_sync = cal_backend_wcap_tasks_receive_objects; object_class->dispose = e_cal_backend_wcap_tasks_dispose; object_class->finalize = e_cal_backend_wcap_tasks_finalize; } static void cal_backend_wcap_tasks_init (CalBackendWCAPTasks *klass) { }