diff options
Diffstat (limited to 'calendar/cal-client/cal-client.c')
-rw-r--r-- | calendar/cal-client/cal-client.c | 3823 |
1 files changed, 0 insertions, 3823 deletions
diff --git a/calendar/cal-client/cal-client.c b/calendar/cal-client/cal-client.c deleted file mode 100644 index f69567b90e..0000000000 --- a/calendar/cal-client/cal-client.c +++ /dev/null @@ -1,3823 +0,0 @@ -/* Evolution calendar client - * - * Copyright (C) 2001 Ximian, Inc. - * - * Author: Federico Mena-Quintero <federico@ximian.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <pthread.h> -#include <string.h> -#include <bonobo-activation/bonobo-activation.h> -#include <bonobo/bonobo-exception.h> -#include <bonobo/bonobo-i18n.h> -#include <libgnome/gnome-util.h> - -#include "e-util/e-component-listener.h" -#include "e-util/e-config-listener.h" -#include "e-util/e-url.h" -#include "e-util/e-msgport.h" -#include "cal-util/cal-util-marshal.h" -#include "cal-util/timeutil.h" -#include "cal-client.h" -#include "cal-listener.h" -#include "query-listener.h" - - - -typedef struct { - EMutex *mutex; - pthread_cond_t cond; - ECalendarStatus status; - - char *uid; - GList *list; - gboolean bool; - char *string; - - CalQuery *query; - QueryListener *listener; -} ECalendarOp; - -/* Private part of the CalClient structure */ -struct _CalClientPrivate { - /* Load state to avoid multiple loads */ - CalClientLoadState load_state; - - /* URI of the calendar that is being loaded or is already loaded, or - * NULL if we are not loaded. - */ - char *uri; - CalObjType type; - - ECalendarOp *current_op; - - EMutex *mutex; - - /* Email address associated with this calendar, or NULL */ - char *cal_address; - char *alarm_email_address; - char *ldap_attribute; - - /* Scheduling info */ - char *capabilities; - - /* The calendar factories we are contacting */ - GList *factories; - - /* Our calendar listener implementation */ - CalListener *listener; - - /* The calendar client interface object we are contacting */ - GNOME_Evolution_Calendar_Cal cal; - - /* The authentication function */ - CalClientAuthFunc auth_func; - gpointer auth_user_data; - - /* A cache of timezones retrieved from the server, to avoid getting - them repeatedly for each get_object() call. */ - GHashTable *timezones; - - /* The default timezone to use to resolve DATE and floating DATE-TIME - values. */ - icaltimezone *default_zone; - - /* The component listener to keep track of the lifetime of backends */ - EComponentListener *comp_listener; -}; - - - -/* Signal IDs */ -enum { - CAL_OPENED, - CAL_SET_MODE, - BACKEND_ERROR, - CATEGORIES_CHANGED, - FORGET_PASSWORD, - BACKEND_DIED, - LAST_SIGNAL -}; - -static void cal_client_get_object_timezones_cb (icalparameter *param, - void *data); - -static guint cal_client_signals[LAST_SIGNAL]; - -static GObjectClass *parent_class; - -#define E_CALENDAR_CHECK_STATUS(status,error) G_STMT_START{ \ - if ((status) == E_CALENDAR_STATUS_OK) { \ - return TRUE; \ - } \ - else { \ - const char *msg; \ - msg = cal_client_get_error_message ((status)); \ - g_set_error ((error), E_CALENDAR_ERROR, (status), msg, (status)); \ - return FALSE; \ - } }G_STMT_END - - - -/* Error quark */ -GQuark -e_calendar_error_quark (void) -{ - static GQuark q = 0; - if (q == 0) - q = g_quark_from_static_string ("e-calendar-error-quark"); - - return q; -} - -GType -cal_client_open_status_enum_get_type (void) -{ - static GType cal_client_open_status_enum_type = 0; - - if (!cal_client_open_status_enum_type) { - static GEnumValue values [] = { - { CAL_CLIENT_OPEN_SUCCESS, "CalClientOpenSuccess", "success" }, - { CAL_CLIENT_OPEN_ERROR, "CalClientOpenError", "error" }, - { CAL_CLIENT_OPEN_NOT_FOUND, "CalClientOpenNotFound", "not-found" }, - { CAL_CLIENT_OPEN_PERMISSION_DENIED, "CalClientOpenPermissionDenied", "denied" }, - { CAL_CLIENT_OPEN_METHOD_NOT_SUPPORTED, "CalClientOpenMethodNotSupported", "unsupported" }, - { -1, NULL, NULL } - }; - - cal_client_open_status_enum_type = g_enum_register_static ("CalClientOpenStatusEnum", values); - } - - return cal_client_open_status_enum_type; -} - -GType -cal_client_set_mode_status_enum_get_type (void) -{ - static GType cal_client_set_mode_status_enum_type = 0; - - if (!cal_client_set_mode_status_enum_type) { - static GEnumValue values [] = { - { CAL_CLIENT_SET_MODE_SUCCESS, "CalClientSetModeSuccess", "success" }, - { CAL_CLIENT_SET_MODE_ERROR, "CalClientSetModeError", "error" }, - { CAL_CLIENT_SET_MODE_NOT_SUPPORTED, "CalClientSetModeNotSupported", "unsupported" }, - { -1, NULL, NULL } - }; - - cal_client_set_mode_status_enum_type = - g_enum_register_static ("CalClientSetModeStatusEnum", values); - } - - return cal_client_set_mode_status_enum_type; -} - -GType -cal_mode_enum_get_type (void) -{ - static GType cal_mode_enum_type = 0; - - if (!cal_mode_enum_type) { - static GEnumValue values [] = { - { CAL_MODE_INVALID, "CalModeInvalid", "invalid" }, - { CAL_MODE_LOCAL, "CalModeLocal", "local" }, - { CAL_MODE_REMOTE, "CalModeRemote", "remote" }, - { CAL_MODE_ANY, "CalModeAny", "any" }, - { -1, NULL, NULL } - }; - - cal_mode_enum_type = g_enum_register_static ("CalModeEnum", values); - } - - return cal_mode_enum_type; -} - -/* EBookOp calls */ - -static ECalendarOp* -e_calendar_new_op (CalClient *client) -{ - ECalendarOp *op = g_new0 (ECalendarOp, 1); - - op->mutex = e_mutex_new (E_MUTEX_SIMPLE); - pthread_cond_init (&op->cond, 0); - - client->priv->current_op = op; - - return op; -} - -static ECalendarOp* -e_calendar_get_op (CalClient *client) -{ - if (!client->priv->current_op) { - g_warning (G_STRLOC ": Unexpected response"); - return NULL; - } - - return client->priv->current_op; -} - -static void -e_calendar_free_op (ECalendarOp *op) -{ - /* XXX more stuff here */ - pthread_cond_destroy (&op->cond); - e_mutex_destroy (op->mutex); - g_free (op); -} - -static void -e_calendar_remove_op (CalClient *client, ECalendarOp *op) -{ - if (client->priv->current_op != op) - g_warning (G_STRLOC ": Cannot remove op, it's not current"); - - client->priv->current_op = NULL; -} - -/* Gets rid of the factories that a client knows about */ -static void -destroy_factories (CalClient *client) -{ - CalClientPrivate *priv; - CORBA_Object factory; - CORBA_Environment ev; - int result; - GList *f; - - priv = client->priv; - - CORBA_exception_init (&ev); - - for (f = priv->factories; f; f = f->next) { - factory = f->data; - - result = CORBA_Object_is_nil (factory, &ev); - if (BONOBO_EX (&ev)) { - g_message ("destroy_factories(): could not see if a factory was nil"); - CORBA_exception_free (&ev); - - continue; - } - - if (result) - continue; - - CORBA_Object_release (factory, &ev); - if (BONOBO_EX (&ev)) { - g_message ("destroy_factories(): could not release a factory"); - CORBA_exception_free (&ev); - } - } - - g_list_free (priv->factories); - priv->factories = NULL; -} - -/* Gets rid of the calendar client interface object that a client knows about */ -static void -destroy_cal (CalClient *client) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - int result; - - priv = client->priv; - - CORBA_exception_init (&ev); - result = CORBA_Object_is_nil (priv->cal, &ev); - if (BONOBO_EX (&ev)) { - g_message (G_STRLOC ": could not see if the " - "calendar client interface object was nil"); - priv->cal = CORBA_OBJECT_NIL; - CORBA_exception_free (&ev); - return; - } - CORBA_exception_free (&ev); - - if (result) - return; - - bonobo_object_release_unref (priv->cal, NULL); - priv->cal = CORBA_OBJECT_NIL; - -} - -static void -free_timezone (gpointer key, gpointer value, gpointer data) -{ - /* Note that the key comes from within the icaltimezone value, so we - don't free that. */ - icaltimezone_free (value, TRUE); -} - - - -static void -backend_died_cb (EComponentListener *cl, gpointer user_data) -{ - CalClientPrivate *priv; - CalClient *client = (CalClient *) user_data; - - g_return_if_fail (IS_CAL_CLIENT (client)); - - priv = client->priv; - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; - g_signal_emit (G_OBJECT (client), cal_client_signals[BACKEND_DIED], 0); -} - -/* Signal handlers for the listener's signals */ -/* Handle the cal_opened notification from the listener */ - -static void -cal_read_only_cb (CalListener *listener, ECalendarStatus status, gboolean read_only, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->bool = read_only; - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_cal_address_cb (CalListener *listener, ECalendarStatus status, const char *address, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->string = g_strdup (address); - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_alarm_address_cb (CalListener *listener, ECalendarStatus status, const char *address, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->string = g_strdup (address); - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_ldap_attribute_cb (CalListener *listener, ECalendarStatus status, const char *attribute, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->string = g_strdup (attribute); - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_static_capabilities_cb (CalListener *listener, ECalendarStatus status, const char *capabilities, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->string = g_strdup (capabilities); - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_opened_cb (CalListener *listener, ECalendarStatus status, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_removed_cb (CalListener *listener, ECalendarStatus status, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_object_created_cb (CalListener *listener, ECalendarStatus status, const char *uid, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->uid = g_strdup (uid); - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_object_modified_cb (CalListener *listener, ECalendarStatus status, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_object_removed_cb (CalListener *listener, ECalendarStatus status, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_alarm_discarded_cb (CalListener *listener, ECalendarStatus status, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_objects_received_cb (CalListener *listener, ECalendarStatus status, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_objects_sent_cb (CalListener *listener, ECalendarStatus status, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_default_object_requested_cb (CalListener *listener, ECalendarStatus status, const char *object, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->string = g_strdup (object); - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_object_requested_cb (CalListener *listener, ECalendarStatus status, const char *object, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->string = g_strdup (object); - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_object_list_cb (CalListener *listener, ECalendarStatus status, GList *objects, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - GList *l; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->list = g_list_copy (objects); - - for (l = op->list; l; l = l->next) - l->data = icalcomponent_new_clone (l->data); - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_get_timezone_cb (CalListener *listener, ECalendarStatus status, const char *object, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->string = g_strdup (object); - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); - -} - -static void -cal_add_timezone_cb (CalListener *listener, ECalendarStatus status, const char *tzid, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->uid = g_strdup (tzid); - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); - -} - -static void -cal_set_default_timezone_cb (CalListener *listener, ECalendarStatus status, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_get_changes_cb (CalListener *listener, ECalendarStatus status, GList *changes, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - GList *l; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->list = g_list_copy (changes); - - for (l = op->list; l; l = l->next) { - CalClientChange *ccc = l->data, *new_ccc; - - new_ccc = g_new (CalClientChange, 1); - new_ccc->comp = cal_component_clone (ccc->comp); - new_ccc->type = ccc->type; - - l->data = new_ccc; - } - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_get_free_busy_cb (CalListener *listener, ECalendarStatus status, GList *freebusy, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - GList *l; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->list = g_list_copy (freebusy); - - for (l = op->list; l; l = l->next) - l->data = cal_component_clone (l->data); - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -static void -cal_query_cb (CalListener *listener, ECalendarStatus status, GNOME_Evolution_Calendar_Query query, gpointer data) -{ - CalClient *client = data; - ECalendarOp *op; - - op = e_calendar_get_op (client); - - if (op == NULL) { - g_warning (G_STRLOC ": Cannot find operation "); - return; - } - - e_mutex_lock (op->mutex); - - op->status = status; - op->query = cal_query_new (query, op->listener, client); - - pthread_cond_signal (&op->cond); - - e_mutex_unlock (op->mutex); -} - -/* Handle the cal_set_mode notification from the listener */ -static void -cal_set_mode_cb (CalListener *listener, - GNOME_Evolution_Calendar_Listener_SetModeStatus status, - GNOME_Evolution_Calendar_CalMode mode, - gpointer data) -{ - CalClient *client; - CalClientPrivate *priv; - CalClientSetModeStatus client_status; - - client = CAL_CLIENT (data); - priv = client->priv; - - client_status = CAL_CLIENT_OPEN_ERROR; - - switch (status) { - case GNOME_Evolution_Calendar_Listener_MODE_SET: - client_status = CAL_CLIENT_SET_MODE_SUCCESS; - break; - case GNOME_Evolution_Calendar_Listener_MODE_NOT_SET: - client_status = CAL_CLIENT_SET_MODE_ERROR; - break; - case GNOME_Evolution_Calendar_Listener_MODE_NOT_SUPPORTED: - client_status = CAL_CLIENT_SET_MODE_NOT_SUPPORTED; - break; - default: - g_assert_not_reached (); - } - - /* We are *not* inside a signal handler (this is just a simple callback - * called from the listener), so there is not a temporary reference to - * the client object. We ref() so that we can safely emit our own - * signal and clean up. - */ - - g_object_ref (G_OBJECT (client)); - - g_signal_emit (G_OBJECT (client), cal_client_signals[CAL_SET_MODE], - 0, client_status, mode); - - g_object_unref (G_OBJECT (client)); -} - -/* Handle the error_occurred signal from the listener */ -static void -backend_error_cb (CalListener *listener, const char *message, gpointer data) -{ - CalClient *client; - - client = CAL_CLIENT (data); - g_signal_emit (G_OBJECT (client), cal_client_signals[BACKEND_ERROR], 0, message); -} - -/* Handle the categories_changed signal from the listener */ -static void -categories_changed_cb (CalListener *listener, const GNOME_Evolution_Calendar_StringSeq *categories, - gpointer data) -{ - CalClient *client; - GPtrArray *cats; - int i; - - client = CAL_CLIENT (data); - - cats = g_ptr_array_new (); - g_ptr_array_set_size (cats, categories->_length); - - for (i = 0; i < categories->_length; i++) - cats->pdata[i] = categories->_buffer[i]; - - g_signal_emit (G_OBJECT (client), cal_client_signals[CATEGORIES_CHANGED], 0, cats); - - g_ptr_array_free (cats, TRUE); -} - - - -static gboolean -get_factories (const char *str_uri, GList **factories) -{ - GNOME_Evolution_Calendar_CalFactory factory; - Bonobo_ServerInfoList *servers; - EUri *uri; - char *query; - int i; - - - /* Determine the protocol and query for factory supporting that */ - uri = e_uri_new (str_uri); - if (!uri) { - g_warning (G_STRLOC ": Invalid uri string"); - - return FALSE; - } - - query = g_strdup_printf ("repo_ids.has ('IDL:GNOME/Evolution/Calendar/CalFactory:1.0')" - " AND calendar:supported_protocols.has ('%s')", uri->protocol); - - - servers = bonobo_activation_query (query, NULL, NULL); - - g_free (query); - e_uri_free (uri); - - if (!servers) { - g_warning (G_STRLOC ": Unable to query for calendar factories"); - - return FALSE; - } - - /* Try to activate the servers for the protocol */ - for (i = 0; i < servers->_length; i++) { - const Bonobo_ServerInfo *info; - - info = servers->_buffer + i; - - g_message (G_STRLOC ": Activating calendar factory (%s)", info->iid); - factory = bonobo_activation_activate_from_id (info->iid, 0, NULL, NULL); - - if (factory == CORBA_OBJECT_NIL) - g_warning (G_STRLOC ": Could not activate calendar factory (%s)", info->iid); - else - *factories = g_list_append (*factories, factory); - } - - CORBA_free (servers); - - return TRUE; -} - -/* Object initialization function for the calendar client */ -static void -cal_client_init (CalClient *client, CalClientClass *klass) -{ - CalClientPrivate *priv; - - priv = g_new0 (CalClientPrivate, 1); - client->priv = priv; - - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; - priv->uri = NULL; - priv->mutex = e_mutex_new (E_MUTEX_REC); - priv->listener = cal_listener_new (cal_set_mode_cb, - backend_error_cb, - categories_changed_cb, - client); - - priv->cal_address = NULL; - priv->alarm_email_address = NULL; - priv->ldap_attribute = NULL; - priv->capabilities = FALSE; - priv->factories = NULL; - priv->timezones = g_hash_table_new (g_str_hash, g_str_equal); - priv->default_zone = icaltimezone_get_utc_timezone (); - priv->comp_listener = NULL; - - g_signal_connect (G_OBJECT (priv->listener), "read_only", G_CALLBACK (cal_read_only_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "cal_address", G_CALLBACK (cal_cal_address_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "alarm_address", G_CALLBACK (cal_alarm_address_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "ldap_attribute", G_CALLBACK (cal_ldap_attribute_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "static_capabilities", G_CALLBACK (cal_static_capabilities_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "open", G_CALLBACK (cal_opened_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "remove", G_CALLBACK (cal_removed_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "create_object", G_CALLBACK (cal_object_created_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "modify_object", G_CALLBACK (cal_object_modified_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "remove_object", G_CALLBACK (cal_object_removed_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "discard_alarm", G_CALLBACK (cal_alarm_discarded_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "receive_objects", G_CALLBACK (cal_objects_received_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "send_objects", G_CALLBACK (cal_objects_sent_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "default_object", G_CALLBACK (cal_default_object_requested_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "object", G_CALLBACK (cal_object_requested_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "object_list", G_CALLBACK (cal_object_list_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "get_timezone", G_CALLBACK (cal_get_timezone_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "add_timezone", G_CALLBACK (cal_add_timezone_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "set_default_timezone", G_CALLBACK (cal_set_default_timezone_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "get_changes", G_CALLBACK (cal_get_changes_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "get_free_busy", G_CALLBACK (cal_get_free_busy_cb), client); - g_signal_connect (G_OBJECT (priv->listener), "query", G_CALLBACK (cal_query_cb), client); -} - -/* Finalize handler for the calendar client */ -static void -cal_client_finalize (GObject *object) -{ - CalClient *client; - CalClientPrivate *priv; - - g_return_if_fail (object != NULL); - g_return_if_fail (IS_CAL_CLIENT (object)); - - client = CAL_CLIENT (object); - priv = client->priv; - - if (priv->listener) { - cal_listener_stop_notification (priv->listener); - bonobo_object_unref (priv->listener); - priv->listener = NULL; - } - - if (priv->comp_listener) { - g_signal_handlers_disconnect_matched (G_OBJECT (priv->comp_listener), - G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, - client); - g_object_unref (G_OBJECT (priv->comp_listener)); - priv->comp_listener = NULL; - } - - destroy_factories (client); - destroy_cal (client); - - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; - - if (priv->uri) { - g_free (priv->uri); - priv->uri = NULL; - } - - if (priv->mutex) { - e_mutex_destroy (priv->mutex); - priv->mutex = NULL; - } - - if (priv->cal_address) { - g_free (priv->cal_address); - priv->cal_address = NULL; - } - if (priv->alarm_email_address) { - g_free (priv->alarm_email_address); - priv->alarm_email_address = NULL; - } - if (priv->ldap_attribute) { - g_free (priv->ldap_attribute); - priv->ldap_attribute = NULL; - } - if (priv->capabilities) { - g_free (priv->capabilities); - priv->capabilities = NULL; - } - - g_hash_table_foreach (priv->timezones, free_timezone, NULL); - g_hash_table_destroy (priv->timezones); - priv->timezones = NULL; - - g_free (priv); - client->priv = NULL; - - if (G_OBJECT_CLASS (parent_class)->finalize) - (* G_OBJECT_CLASS (parent_class)->finalize) (object); -} - -/* Class initialization function for the calendar client */ -static void -cal_client_class_init (CalClientClass *klass) -{ - GObjectClass *object_class; - - object_class = (GObjectClass *) klass; - - parent_class = g_type_class_peek_parent (klass); - - cal_client_signals[CAL_OPENED] = - g_signal_new ("cal_opened", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, cal_opened), - NULL, NULL, - g_cclosure_marshal_VOID__ENUM, - G_TYPE_NONE, 1, - CAL_CLIENT_OPEN_STATUS_ENUM_TYPE); - cal_client_signals[CAL_SET_MODE] = - g_signal_new ("cal_set_mode", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, cal_set_mode), - NULL, NULL, - cal_util_marshal_VOID__ENUM_ENUM, - G_TYPE_NONE, 2, - CAL_CLIENT_SET_MODE_STATUS_ENUM_TYPE, - CAL_MODE_ENUM_TYPE); - cal_client_signals[BACKEND_ERROR] = - g_signal_new ("backend_error", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, backend_error), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - cal_client_signals[CATEGORIES_CHANGED] = - g_signal_new ("categories_changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, categories_changed), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, - G_TYPE_POINTER); - cal_client_signals[FORGET_PASSWORD] = - g_signal_new ("forget_password", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, forget_password), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, - G_TYPE_STRING); - cal_client_signals[BACKEND_DIED] = - g_signal_new ("backend_died", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (CalClientClass, backend_died), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - klass->cal_opened = NULL; - klass->categories_changed = NULL; - klass->forget_password = NULL; - klass->backend_died = NULL; - - object_class->finalize = cal_client_finalize; -} - -/** - * cal_client_get_type: - * - * Registers the #CalClient class if necessary, and returns the type ID assigned - * to it. - * - * Return value: The type ID of the #CalClient class. - **/ -GType -cal_client_get_type (void) -{ - static GType cal_client_type = 0; - - if (!cal_client_type) { - static GTypeInfo info = { - sizeof (CalClientClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) cal_client_class_init, - NULL, NULL, - sizeof (CalClient), - 0, - (GInstanceInitFunc) cal_client_init - }; - cal_client_type = g_type_register_static (G_TYPE_OBJECT, "CalClient", &info, 0); - } - - return cal_client_type; -} - - -static gboolean -fetch_corba_cal (CalClient *client, const char *str_uri, CalObjType type) -{ - CalClientPrivate *priv; - GList *f; - CORBA_Environment ev; - - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_NOT_LOADED, FALSE); - g_assert (priv->uri == NULL); - - g_return_val_if_fail (str_uri != NULL, FALSE); - - if (!get_factories (str_uri, &priv->factories)) - return FALSE; - - priv->uri = g_strdup (str_uri); - priv->type = type; - - for (f = priv->factories; f; f = f->next) { - GNOME_Evolution_Calendar_Cal cal; - - CORBA_exception_init (&ev); - - cal = GNOME_Evolution_Calendar_CalFactory_getCal (f->data, priv->uri, priv->type, - BONOBO_OBJREF (priv->listener), &ev); - if (BONOBO_EX (&ev)) - continue; - - priv->cal = cal; - - return TRUE; - } - - return FALSE; -} - -/** - * cal_client_new: - * - * Creates a new calendar client. It should be initialized by calling - * cal_client_open(). - * - * Return value: A newly-created calendar client, or NULL if the client could - * not be constructed because it could not contact the calendar server. - **/ -CalClient * -cal_client_new (const char *uri, CalObjType type) -{ - CalClient *client; - - client = g_object_new (CAL_CLIENT_TYPE, NULL); - - if (!fetch_corba_cal (client, uri, type)) { - g_object_unref (client); - - return NULL; - } - - return client; -} - -/** - * cal_client_set_auth_func - * @client: A calendar client. - * @func: The authentication function - * @data: User data to be used when calling the authentication function - * - * Associates the given authentication function with a calendar client. This - * function will be called any time the calendar server needs a password - * from the client. So, calendar clients should provide such authentication - * function, which, when called, should act accordingly (by showing a dialog - * box, for example, to ask the user for the password). - * - * The authentication function must have the following form: - * char * auth_func (CalClient *client, - * const gchar *prompt, - * const gchar *key, - * gpointer user_data) - */ -void -cal_client_set_auth_func (CalClient *client, CalClientAuthFunc func, gpointer data) -{ - g_return_if_fail (client != NULL); - g_return_if_fail (IS_CAL_CLIENT (client)); - - client->priv->auth_func = func; - client->priv->auth_user_data = data; -} - -/** - * cal_client_open - * @client: A calendar client. - * @str_uri: URI of calendar to open. - * @only_if_exists: FALSE if the calendar should be opened even if there - * was no storage for it, i.e. to create a new calendar or load an existing - * one if it already exists. TRUE if it should only try to load calendars - * that already exist. - * - * Makes a calendar client initiate a request to open a calendar. The calendar - * client will emit the "cal_opened" signal when the response from the server is - * received. - * - * Return value: TRUE on success, FALSE on failure to issue the open request. - **/ -gboolean -cal_client_open (CalClient *client, gboolean only_if_exists, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - CORBA_exception_init (&ev); - - priv->load_state = CAL_CLIENT_LOAD_LOADING; - - GNOME_Evolution_Calendar_Cal_open (priv->cal, only_if_exists, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - g_signal_emit (G_OBJECT (client), cal_client_signals[CAL_OPENED], 0, - E_CALENDAR_STATUS_CORBA_EXCEPTION); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - if (status == E_CALENDAR_STATUS_OK) - priv->load_state = CAL_CLIENT_LOAD_LOADED; - else - priv->load_state = CAL_CLIENT_LOAD_NOT_LOADED; - - g_signal_emit (G_OBJECT (client), cal_client_signals[CAL_OPENED], 0, status); - E_CALENDAR_CHECK_STATUS (status, error); -} - -typedef struct { - CalClient *client; - - gboolean exists; -} CalClientAsyncData; - -static gboolean -open_async (gpointer data) -{ - CalClientAsyncData *ccad = data; - GError *error = NULL; - - cal_client_open (ccad->client, ccad->exists, &error); - - g_clear_error (&error); - - g_object_unref (ccad); - g_free (ccad); - - return FALSE; -} - -void -cal_client_open_async (CalClient *client, gboolean only_if_exists) -{ - CalClientAsyncData *ccad; - - g_return_if_fail (client != NULL); - g_return_if_fail (IS_CAL_CLIENT (client)); - - ccad = g_new0 (CalClientAsyncData, 1); - ccad->client = g_object_ref (client); - ccad->exists = only_if_exists; - - /* FIXME This should really spawn a new thread */ - g_idle_add (open_async, ccad); -} - -gboolean -cal_client_remove_calendar (CalClient *client, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_remove (priv->cal, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -#if 0 -/* Builds an URI list out of a CORBA string sequence */ -static GList * -build_uri_list (GNOME_Evolution_Calendar_StringSeq *seq) -{ - GList *uris = NULL; - int i; - - for (i = 0; i < seq->_length; i++) - uris = g_list_prepend (uris, g_strdup (seq->_buffer[i])); - - return uris; -} -#endif - -/** - * cal_client_uri_list: - * @client: A calendar client - * @type: type of uri's to get - * - * - * Return value: A list of URI's open on the wombat - **/ -GList * -cal_client_uri_list (CalClient *client, CalMode mode) -{ -#if 0 - CalClientPrivate *priv; - GNOME_Evolution_Calendar_StringSeq *uri_seq; - GList *uris = NULL; - CORBA_Environment ev; - GList *f; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - for (f = priv->factories; f; f = f->next) { - CORBA_exception_init (&ev); - uri_seq = GNOME_Evolution_Calendar_CalFactory_uriList (f->data, mode, &ev); - - if (BONOBO_EX (&ev)) { - g_message ("cal_client_uri_list(): request failed"); - - /* free memory and return */ - g_list_foreach (uris, (GFunc) g_free, NULL); - g_list_free (uris); - uris = NULL; - break; - } - else { - uris = g_list_concat (uris, build_uri_list (uri_seq)); - CORBA_free (uri_seq); - } - - CORBA_exception_free (&ev); - } - - return uris; -#endif - - return NULL; -} - - -/** - * cal_client_get_load_state: - * @client: A calendar client. - * - * Queries the state of loading of a calendar client. - * - * Return value: A #CalClientLoadState value indicating whether the client has - * not been loaded with cal_client_open_calendar() yet, whether it is being - * loaded, or whether it is already loaded. - **/ -CalClientLoadState -cal_client_get_load_state (CalClient *client) -{ - CalClientPrivate *priv; - - g_return_val_if_fail (client != NULL, CAL_CLIENT_LOAD_NOT_LOADED); - g_return_val_if_fail (IS_CAL_CLIENT (client), CAL_CLIENT_LOAD_NOT_LOADED); - - priv = client->priv; - return priv->load_state; -} - -/** - * cal_client_get_uri: - * @client: A calendar client. - * - * Queries the URI that is open in a calendar client. - * - * Return value: The URI of the calendar that is already loaded or is being - * loaded, or NULL if the client has not started a load request yet. - **/ -const char * -cal_client_get_uri (CalClient *client) -{ - CalClientPrivate *priv; - - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); - - priv = client->priv; - return priv->uri; -} - -/** - * cal_client_is_read_only: - * @client: A calendar client. - * - * Queries whether the calendar client can perform modifications - * on the calendar or not. Whether the backend is read only or not - * is specified, on exit, in the @read_only argument. - * - * Return value: TRUE if the call was successful, FALSE if there was an error. - */ -gboolean -cal_client_is_read_only (CalClient *client, gboolean *read_only, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_isReadOnly (priv->cal, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - *read_only = our_op->bool; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - return status; -} - -/** - * cal_client_get_cal_address: - * @client: A calendar client. - * - * Queries the calendar address associated with a calendar client. - * - * Return value: The calendar address associated with the calendar that - * is loaded or being loaded, or %NULL if the client has not started a - * load request yet or the calendar has no associated email address. - **/ -gboolean -cal_client_get_cal_address (CalClient *client, char **cal_address, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_getCalAddress (priv->cal, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - *cal_address = our_op->string; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -gboolean -cal_client_get_alarm_email_address (CalClient *client, char **alarm_address, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_getAlarmEmailAddress (priv->cal, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - *alarm_address = our_op->string; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -gboolean -cal_client_get_ldap_attribute (CalClient *client, char **ldap_attribute, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_getLdapAttribute (priv->cal, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - *ldap_attribute = our_op->string; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -static gboolean -load_static_capabilities (CalClient *client, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - char *cap; - - priv = client->priv; - - if (priv->capabilities) - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error); - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_getStaticCapabilities (priv->cal, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - cap = our_op->string; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -static gboolean -check_capability (CalClient *client, const char *cap) -{ - CalClientPrivate *priv; - - priv = client->priv; - - /* FIXME Check result */ - load_static_capabilities (client, NULL); - if (priv->capabilities && strstr (priv->capabilities, cap)) - return TRUE; - - return FALSE; -} - -gboolean -cal_client_get_one_alarm_only (CalClient *client) -{ - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - return check_capability (client, CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY); -} - -gboolean -cal_client_get_organizer_must_attend (CalClient *client) -{ - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - return check_capability (client, CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ATTEND); -} - -gboolean -cal_client_get_static_capability (CalClient *client, const char *cap) -{ - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - return check_capability (client, cap); -} - -gboolean -cal_client_get_save_schedules (CalClient *client) -{ - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - return check_capability (client, CAL_STATIC_CAPABILITY_SAVE_SCHEDULES); -} - -gboolean -cal_client_set_mode (CalClient *client, CalMode mode) -{ - CalClientPrivate *priv; - gboolean retval = TRUE; - CORBA_Environment ev; - - g_return_val_if_fail (client != NULL, -1); - g_return_val_if_fail (IS_CAL_CLIENT (client), -1); - - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, -1); - - CORBA_exception_init (&ev); - GNOME_Evolution_Calendar_Cal_setMode (priv->cal, mode, &ev); - - if (BONOBO_EX (&ev)) - retval = FALSE; - - CORBA_exception_free (&ev); - - return retval; -} - - -/* This is used in the callback which fetches all the timezones needed for an - object. */ -typedef struct _CalClientGetTimezonesData CalClientGetTimezonesData; -struct _CalClientGetTimezonesData { - CalClient *client; - - /* This starts out at E_CALENDAR_STATUS_OK. If an error occurs this - contains the last error. */ - ECalendarStatus status; -}; - -gboolean -cal_client_get_default_object (CalClient *client, icalcomponent **icalcomp, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_getDefaultObject (priv->cal, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - *icalcomp = icalparser_parse_string (our_op->string); - g_free (our_op->string); - - if (!*icalcomp) { - status = E_CALENDAR_STATUS_INVALID_OBJECT; - } else { - CalClientGetTimezonesData cb_data; - - /* Now make sure we have all timezones needed for this object. - We do this to try to avoid any problems caused by getting a timezone - in the middle of other code. Any calls to ORBit result in a - recursive call of the GTK+ main loop, which can cause problems for - code that doesn't expect it. Currently GnomeCanvas has problems if - we try to get a timezone in the middle of a redraw, and there is a - resize pending, which leads to an assert failure and an abort. */ - cb_data.client = client; - cb_data.status = E_CALENDAR_STATUS_OK; - icalcomponent_foreach_tzid (*icalcomp, - cal_client_get_object_timezones_cb, - &cb_data); - - status = cb_data.status; - } - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -/** - * cal_client_get_object: - * @client: A calendar client. - * @uid: Unique identifier for a calendar component. - * @icalcomp: Return value for the calendar component object. - * - * Queries a calendar for a calendar component object based on its unique - * identifier. - * - * Return value: Result code based on the status of the operation. - **/ -gboolean -cal_client_get_object (CalClient *client, const char *uid, const char *rid, icalcomponent **icalcomp, GError **error) -{ - - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_getObject (priv->cal, uid, rid ? rid : "", &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - *icalcomp = icalparser_parse_string (our_op->string); - g_free (our_op->string); - - if (status == E_CALENDAR_STATUS_OK && !*icalcomp) { - status = E_CALENDAR_STATUS_INVALID_OBJECT; - } else if (status == E_CALENDAR_STATUS_OK){ - CalClientGetTimezonesData cb_data; - - /* Now make sure we have all timezones needed for this object. - We do this to try to avoid any problems caused by getting a timezone - in the middle of other code. Any calls to ORBit result in a - recursive call of the GTK+ main loop, which can cause problems for - code that doesn't expect it. Currently GnomeCanvas has problems if - we try to get a timezone in the middle of a redraw, and there is a - resize pending, which leads to an assert failure and an abort. */ - cb_data.client = client; - cb_data.status = E_CALENDAR_STATUS_OK; - icalcomponent_foreach_tzid (*icalcomp, - cal_client_get_object_timezones_cb, - &cb_data); - - status = cb_data.status; - } - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - - -static void -cal_client_get_object_timezones_cb (icalparameter *param, - void *data) -{ - CalClientGetTimezonesData *cb_data = data; - const char *tzid; - icaltimezone *zone; - GError *error = NULL; - - tzid = icalparameter_get_tzid (param); - if (!tzid) { - cb_data->status = E_CALENDAR_STATUS_INVALID_OBJECT; - return; - } - - if (!cal_client_get_timezone (cb_data->client, tzid, &zone, &error)) - cb_data->status = error->code; - - g_clear_error (&error); -} - -/* Resolves TZIDs for the recurrence generator. */ -icaltimezone* -cal_client_resolve_tzid_cb (const char *tzid, gpointer data) -{ - CalClient *client; - icaltimezone *zone = NULL; - - g_return_val_if_fail (data != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (data), NULL); - - client = CAL_CLIENT (data); - - /* FIXME: Handle errors. */ - cal_client_get_timezone (client, tzid, &zone, NULL); - - return zone; -} - -gboolean -cal_client_get_changes (CalClient *client, const char *change_id, GList **changes, GError **error) -{ - CORBA_Environment ev; - ECalendarOp *our_op; - ECalendarStatus status; - - g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); - g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); - g_return_val_if_fail (change_id != NULL, E_CALENDAR_STATUS_INVALID_ARG); - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_getChanges (client->priv->cal, change_id, &ev); - - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - *changes = our_op->list; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - - -/** - * cal_client_get_object_list: - * @client: - * @query: - * - * - * - * Return value: - **/ -gboolean -cal_client_get_object_list (CalClient *client, const char *query, GList **objects, GError **error) -{ - CORBA_Environment ev; - ECalendarOp *our_op; - ECalendarStatus status; - - g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); - g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); - g_return_val_if_fail (query != NULL, E_CALENDAR_STATUS_INVALID_ARG); - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_getObjectList (client->priv->cal, query, &ev); - - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - *objects = our_op->list; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -gboolean -cal_client_get_object_list_as_comp (CalClient *client, const char *query, GList **objects, GError **error) -{ - GList *ical_objects = NULL; - GList *l; - - g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); - g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); - g_return_val_if_fail (query != NULL, E_CALENDAR_STATUS_INVALID_ARG); - g_return_val_if_fail (objects != NULL, E_CALENDAR_STATUS_INVALID_ARG); - - if (!cal_client_get_object_list (client, query, &ical_objects, error)) - return FALSE; - - *objects = NULL; - for (l = ical_objects; l; l = l->next) { - CalComponent *comp; - - comp = cal_component_new (); - cal_component_set_icalcomponent (comp, l->data); - *objects = g_list_prepend (*objects, comp); - } - - g_list_free (ical_objects); - - return TRUE; -} - -void -cal_client_free_object_list (GList *objects) -{ - GList *l; - - for (l = objects; l; l = l->next) - icalcomponent_free (l->data); - - g_list_free (objects); -} - -/** - * cal_client_get_free_busy - * @client:: A calendar client. - * @users: List of users to retrieve free/busy information for. - * @start: Start time for query. - * @end: End time for query. - * - * Gets free/busy information from the calendar server. - * - * Returns: a GList of VFREEBUSY CalComponents - */ -gboolean -cal_client_get_free_busy (CalClient *client, GList *users, time_t start, time_t end, - GList **freebusy, GError **error) -{ - CORBA_Environment ev; - ECalendarOp *our_op; - ECalendarStatus status; - GNOME_Evolution_Calendar_UserList corba_users; - GList *l; - int i, len; - - g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); - g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - /* create the CORBA user list to be passed to the backend */ - len = g_list_length (users); - - corba_users._length = len; - corba_users._buffer = CORBA_sequence_GNOME_Evolution_Calendar_User_allocbuf (len); - - for (l = users, i = 0; l; l = l->next, i++) - corba_users._buffer[i] = CORBA_string_dup (l->data); - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_getFreeBusy (client->priv->cal, &corba_users, start, end, &ev); - - CORBA_free (corba_users._buffer); - - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - - *freebusy = NULL; - for (l = our_op->list; l; l = l->next) { - CalComponent *comp; - - icalcomponent *icalcomp; - icalcomponent_kind kind; - - icalcomp = icalparser_parse_string (l->data); - if (!icalcomp) - continue; - - kind = icalcomponent_isa (icalcomp); - if (kind == ICAL_VFREEBUSY_COMPONENT) { - comp = cal_component_new (); - if (!cal_component_set_icalcomponent (comp, icalcomp)) { - icalcomponent_free (icalcomp); - g_object_unref (G_OBJECT (comp)); - continue; - } - - *freebusy = g_list_append (*freebusy, comp); - } - else - icalcomponent_free (icalcomp); - } - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -struct comp_instance { - CalComponent *comp; - time_t start; - time_t end; -}; - -/* Called from cal_recur_generate_instances(); adds an instance to the list */ -static gboolean -add_instance (CalComponent *comp, time_t start, time_t end, gpointer data) -{ - GList **list; - struct comp_instance *ci; - - list = data; - - ci = g_new (struct comp_instance, 1); - - ci->comp = comp; - g_object_ref (G_OBJECT (ci->comp)); - - ci->start = start; - ci->end = end; - - *list = g_list_prepend (*list, ci); - - return TRUE; -} - -/* Used from g_list_sort(); compares two struct comp_instance structures */ -static gint -compare_comp_instance (gconstpointer a, gconstpointer b) -{ - const struct comp_instance *cia, *cib; - time_t diff; - - cia = a; - cib = b; - - diff = cia->start - cib->start; - return (diff < 0) ? -1 : (diff > 0) ? 1 : 0; -} - -/** - * cal_client_generate_instances: - * @client: A calendar client. - * @type: Bitmask with types of objects to return. - * @start: Start time for query. - * @end: End time for query. - * @cb: Callback for each generated instance. - * @cb_data: Closure data for the callback. - * - * Does a combination of cal_client_get_object_list () and - * cal_recur_generate_instances(). - * - * The callback function should do a g_object_ref() of the calendar component - * it gets passed if it intends to keep it around. - **/ -void -cal_client_generate_instances (CalClient *client, CalObjType type, - time_t start, time_t end, - CalRecurInstanceFn cb, gpointer cb_data) -{ - CalClientPrivate *priv; - GList *objects; - GList *instances; - GList *l; - char *query; - - g_return_if_fail (client != NULL); - g_return_if_fail (IS_CAL_CLIENT (client)); - - priv = client->priv; - g_return_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED); - - g_return_if_fail (start != -1 && end != -1); - g_return_if_fail (start <= end); - g_return_if_fail (cb != NULL); - - /* Generate objects */ - query = g_strdup_printf ("(occur-in-time-range? (%lu) (%lu))", start, end); - if (!cal_client_get_object_list (client, query, &objects, NULL)) { - g_free (query); - return; - } - g_free (query); - - instances = NULL; - - for (l = objects; l; l = l->next) { - CalComponent *comp; - - comp = l->data; - cal_recur_generate_instances (comp, start, end, add_instance, &instances, - cal_client_resolve_tzid_cb, client, - priv->default_zone); - g_object_unref (G_OBJECT (comp)); - } - - g_list_free (objects); - - /* Generate instances and spew them out */ - - instances = g_list_sort (instances, compare_comp_instance); - - for (l = instances; l; l = l->next) { - struct comp_instance *ci; - gboolean result; - - ci = l->data; - - result = (* cb) (ci->comp, ci->start, ci->end, cb_data); - - if (!result) - break; - } - - /* Clean up */ - - for (l = instances; l; l = l->next) { - struct comp_instance *ci; - - ci = l->data; - g_object_unref (G_OBJECT (ci->comp)); - g_free (ci); - } - - g_list_free (instances); -} - -/* Builds a list of CalComponentAlarms structures */ -static GSList * -build_component_alarms_list (CalClient *client, GList *object_list, time_t start, time_t end) -{ - GSList *comp_alarms; - GList *l; - - comp_alarms = NULL; - - for (l = object_list; l != NULL; l = l->next) { - CalComponent *comp; - CalComponentAlarms *alarms; - icalcomponent *icalcomp; - CalAlarmAction omit[] = {-1}; - - icalcomp = icalparser_parse_string (l->data); - if (!icalcomp) - continue; - - comp = cal_component_new (); - if (!cal_component_set_icalcomponent (comp, icalcomp)) { - icalcomponent_free (icalcomp); - g_object_unref (G_OBJECT (comp)); - continue; - } - - alarms = cal_util_generate_alarms_for_comp (comp, start, end, omit, cal_client_resolve_tzid_cb, - icalcomp, client->priv->default_zone); - if (alarms) - comp_alarms = g_slist_prepend (comp_alarms, alarms); - } - - return comp_alarms; -} - -/** - * cal_client_get_alarms_in_range: - * @client: A calendar client. - * @start: Start time for query. - * @end: End time for query. - * - * Queries a calendar for the alarms that trigger in the specified range of - * time. - * - * Return value: A list of #CalComponentAlarms structures. This should be freed - * using the cal_client_free_alarms() function, or by freeing each element - * separately with cal_component_alarms_free() and then freeing the list with - * g_slist_free(). - **/ -GSList * -cal_client_get_alarms_in_range (CalClient *client, time_t start, time_t end) -{ - CalClientPrivate *priv; - GSList *alarms; - char *sexp; - GList *object_list = NULL; - - g_return_val_if_fail (client != NULL, NULL); - g_return_val_if_fail (IS_CAL_CLIENT (client), NULL); - - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, NULL); - - g_return_val_if_fail (start != -1 && end != -1, NULL); - g_return_val_if_fail (start <= end, NULL); - - /* build the query string */ - sexp = g_strdup ("(and (has-alarms? #t))"); - - /* execute the query on the server */ - if (!cal_client_get_object_list (client, sexp, &object_list, NULL)) { - g_free (sexp); - return NULL; - } - - alarms = build_component_alarms_list (client, object_list, start, end); - - g_list_foreach (object_list, (GFunc) g_free, NULL); - g_list_free (object_list); - g_free (sexp); - - return alarms; -} - -/** - * cal_client_free_alarms: - * @comp_alarms: A list of #CalComponentAlarms structures. - * - * Frees a list of #CalComponentAlarms structures as returned by - * cal_client_get_alarms_in_range(). - **/ -void -cal_client_free_alarms (GSList *comp_alarms) -{ - GSList *l; - - for (l = comp_alarms; l; l = l->next) { - CalComponentAlarms *alarms; - - alarms = l->data; - g_assert (alarms != NULL); - - cal_component_alarms_free (alarms); - } - - g_slist_free (comp_alarms); -} - -/** - * cal_client_get_alarms_for_object: - * @client: A calendar client. - * @uid: Unique identifier for a calendar component. - * @start: Start time for query. - * @end: End time for query. - * @alarms: Return value for the component's alarm instances. Will return NULL - * if no instances occur within the specified time range. This should be freed - * using the cal_component_alarms_free() function. - * - * Queries a calendar for the alarms of a particular object that trigger in the - * specified range of time. - * - * Return value: TRUE on success, FALSE if the object was not found. - **/ -gboolean -cal_client_get_alarms_for_object (CalClient *client, const char *uid, - time_t start, time_t end, - CalComponentAlarms **alarms) -{ - CalClientPrivate *priv; - icalcomponent *icalcomp; - CalComponent *comp; - CalAlarmAction omit[] = {-1}; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - g_return_val_if_fail (priv->load_state == CAL_CLIENT_LOAD_LOADED, FALSE); - - g_return_val_if_fail (uid != NULL, FALSE); - g_return_val_if_fail (start != -1 && end != -1, FALSE); - g_return_val_if_fail (start <= end, FALSE); - g_return_val_if_fail (alarms != NULL, FALSE); - - *alarms = NULL; - - if (!cal_client_get_object (client, uid, NULL, &icalcomp, NULL)) - return FALSE; - if (!icalcomp) - return FALSE; - - comp = cal_component_new (); - if (!cal_component_set_icalcomponent (comp, icalcomp)) { - icalcomponent_free (icalcomp); - g_object_unref (G_OBJECT (comp)); - return FALSE; - } - - *alarms = cal_util_generate_alarms_for_comp (comp, start, end, omit, cal_client_resolve_tzid_cb, - icalcomp, priv->default_zone); - - return TRUE; -} - -/** - * cal_client_discard_alarm - * @client: A calendar client. - * @comp: The component to discard the alarm from. - * @auid: Unique identifier of the alarm to be discarded. - * - * Tells the calendar backend to get rid of the alarm identified by the - * @auid argument in @comp. Some backends might remove the alarm or - * update internal information about the alarm be discarded, or, like - * the file backend does, ignore the operation. - * - * Return value: a #CalClientResult value indicating the result of the - * operation. - */ -gboolean -cal_client_discard_alarm (CalClient *client, CalComponent *comp, const char *auid, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - const char *uid; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - cal_component_get_uid (comp, &uid); - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_discardAlarm (priv->cal, uid, auid, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -typedef struct _ForeachTZIDCallbackData ForeachTZIDCallbackData; -struct _ForeachTZIDCallbackData { - CalClient *client; - GHashTable *timezone_hash; - gboolean include_all_timezones; - gboolean success; -}; - -/* This adds the VTIMEZONE given by the TZID parameter to the GHashTable in - data. */ -static void -foreach_tzid_callback (icalparameter *param, void *cbdata) -{ - ForeachTZIDCallbackData *data = cbdata; - CalClientPrivate *priv; - const char *tzid; - icaltimezone *zone; - icalcomponent *vtimezone_comp; - char *vtimezone_as_string; - - priv = data->client->priv; - - /* Get the TZID string from the parameter. */ - tzid = icalparameter_get_tzid (param); - if (!tzid) - return; - - /* Check if we've already added it to the GHashTable. */ - if (g_hash_table_lookup (data->timezone_hash, tzid)) - return; - - if (data->include_all_timezones) { - if (!cal_client_get_timezone (data->client, tzid, &zone, NULL)) { - data->success = FALSE; - return; - } - } else { - /* Check if it is in our cache. If it is, it must already be - on the server so return. */ - if (g_hash_table_lookup (priv->timezones, tzid)) - return; - - /* Check if it is a builtin timezone. If it isn't, return. */ - zone = icaltimezone_get_builtin_timezone_from_tzid (tzid); - if (!zone) - return; - } - - /* Convert it to a string and add it to the hash. */ - vtimezone_comp = icaltimezone_get_component (zone); - if (!vtimezone_comp) - return; - - vtimezone_as_string = icalcomponent_as_ical_string (vtimezone_comp); - - g_hash_table_insert (data->timezone_hash, (char*) tzid, - g_strdup (vtimezone_as_string)); -} - -/* This appends the value string to the GString given in data. */ -static void -append_timezone_string (gpointer key, gpointer value, gpointer data) -{ - GString *vcal_string = data; - - g_string_append (vcal_string, value); - g_free (value); -} - - -/* This simply frees the hash values. */ -static void -free_timezone_string (gpointer key, gpointer value, gpointer data) -{ - g_free (value); -} - - -/* This converts the VEVENT/VTODO to a string. If include_all_timezones is - TRUE, it includes all the VTIMEZONE components needed for the VEVENT/VTODO. - If not, it only includes builtin timezones that may not be on the server. - - To do that we check every TZID in the component to see if it is a builtin - timezone. If it is, we see if it it in our cache. If it is in our cache, - then we know the server already has it and we don't need to send it. - If it isn't in our cache, then we need to send it to the server. - If we need to send any timezones to the server, then we have to create a - complete VCALENDAR object, otherwise we can just send a single VEVENT/VTODO - as before. */ -static char* -cal_client_get_component_as_string_internal (CalClient *client, - icalcomponent *icalcomp, - gboolean include_all_timezones) -{ - GHashTable *timezone_hash; - GString *vcal_string; - int initial_vcal_string_len; - ForeachTZIDCallbackData cbdata; - char *obj_string; - CalClientPrivate *priv; - - priv = client->priv; - - timezone_hash = g_hash_table_new (g_str_hash, g_str_equal); - - /* Add any timezones needed to the hash. We use a hash since we only - want to add each timezone once at most. */ - cbdata.client = client; - cbdata.timezone_hash = timezone_hash; - cbdata.include_all_timezones = include_all_timezones; - cbdata.success = TRUE; - icalcomponent_foreach_tzid (icalcomp, foreach_tzid_callback, &cbdata); - if (!cbdata.success) { - g_hash_table_foreach (timezone_hash, free_timezone_string, - NULL); - return NULL; - } - - /* Create the start of a VCALENDAR, to add the VTIMEZONES to, - and remember its length so we know if any VTIMEZONEs get added. */ - vcal_string = g_string_new (NULL); - g_string_append (vcal_string, - "BEGIN:VCALENDAR\n" - "PRODID:-//Ximian//NONSGML Evolution Calendar//EN\n" - "VERSION:2.0\n" - "METHOD:PUBLISH\n"); - initial_vcal_string_len = vcal_string->len; - - /* Now concatenate all the timezone strings. This also frees the - timezone strings as it goes. */ - g_hash_table_foreach (timezone_hash, append_timezone_string, - vcal_string); - - /* Get the string for the VEVENT/VTODO. */ - obj_string = g_strdup (icalcomponent_as_ical_string (icalcomp)); - - /* If there were any timezones to send, create a complete VCALENDAR, - else just send the VEVENT/VTODO string. */ - if (!include_all_timezones - && vcal_string->len == initial_vcal_string_len) { - g_string_free (vcal_string, TRUE); - } else { - g_string_append (vcal_string, obj_string); - g_string_append (vcal_string, "END:VCALENDAR\n"); - g_free (obj_string); - obj_string = vcal_string->str; - g_string_free (vcal_string, FALSE); - } - - g_hash_table_destroy (timezone_hash); - - return obj_string; -} - -/** - * cal_client_get_component_as_string: - * @client: A calendar client. - * @icalcomp: A calendar component object. - * - * Gets a calendar component as an iCalendar string, with a toplevel - * VCALENDAR component and all VTIMEZONEs needed for the component. - * - * Return value: the component as a complete iCalendar string, or NULL on - * failure. The string should be freed after use. - **/ -char* -cal_client_get_component_as_string (CalClient *client, icalcomponent *icalcomp) -{ - return cal_client_get_component_as_string_internal (client, icalcomp, TRUE); -} - -gboolean -cal_client_create_object (CalClient *client, icalcomponent *icalcomp, char **uid, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_createObject (priv->cal, icalcomponent_as_ical_string (icalcomp), &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - if (uid) - *uid = our_op->uid; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -gboolean -cal_client_modify_object (CalClient *client, icalcomponent *icalcomp, CalObjModType mod, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - g_return_val_if_fail (icalcomp != NULL, FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_modifyObject (priv->cal, icalcomponent_as_ical_string (icalcomp), mod, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -gboolean -cal_client_remove_object_with_mod (CalClient *client, const char *uid, - const char *rid, CalObjModType mod, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_removeObject (priv->cal, uid, rid ? rid : "", mod, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -/** - * cal_client_remove_object: - * @client: A calendar client. - * @uid: Unique identifier of the calendar component to remove. - * - * Asks a calendar to remove a component. If the server is able to remove the - * component, all clients will be notified and they will emit the "obj_removed" - * signal. - * - * Return value: a #CalClientResult value indicating the result of the - * operation. - **/ -gboolean -cal_client_remove_object (CalClient *client, const char *uid, GError **error) -{ - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - return cal_client_remove_object_with_mod (client, uid, NULL, CALOBJ_MOD_ALL, error); -} - -gboolean -cal_client_receive_objects (CalClient *client, icalcomponent *icalcomp, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_receiveObjects (priv->cal, icalcomponent_as_ical_string (icalcomp), &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -gboolean -cal_client_send_objects (CalClient *client, icalcomponent *icalcomp, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - - g_return_val_if_fail (client != NULL, FALSE); - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - - priv = client->priv; - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_sendObjects (priv->cal, icalcomponent_as_ical_string (icalcomp), &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -gboolean -cal_client_get_timezone (CalClient *client, const char *tzid, icaltimezone **zone, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - icalcomponent *icalcomp; - - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - g_return_val_if_fail (tzid != NULL, FALSE); - - priv = client->priv; - - e_mutex_lock (priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (priv->mutex); - - /* Check for well known zones and in the cache */ - *zone = NULL; - - /* If tzid is NULL or "" we return NULL, since it is a 'local time'. */ - if (!tzid || !tzid[0]) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error); - } - - /* If it is UTC, we return the special UTC timezone. */ - if (!strcmp (tzid, "UTC")) { - *zone = icaltimezone_get_utc_timezone (); - } else { - /* See if we already have it in the cache. */ - *zone = g_hash_table_lookup (priv->timezones, tzid); - } - - if (*zone) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OK, error); - } - - /* call the backend */ - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_getTimezone (priv->cal, tzid, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - - icalcomp = icalparser_parse_string (our_op->string); - g_free (our_op->string); - - /* FIXME Invalid object status? */ - if (!icalcomp) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OBJECT_NOT_FOUND, error); - } - - *zone = icaltimezone_new (); - if (!icaltimezone_set_component (*zone, icalcomp)) { - icaltimezone_free (*zone, 1); - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_OBJECT_NOT_FOUND, error); - } - - /* Now add it to the cache, to avoid the server call in future. */ - g_hash_table_insert (priv->timezones, icaltimezone_get_tzid (*zone), *zone); - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -/** - * cal_client_add_timezone - * @client: A calendar client. - * @izone: The timezone to add. - * @error: Placeholder for error information. - * - * Add a VTIMEZONE object to the given calendar. - * - * Returns: TRUE if successful, FALSE otherwise. - */ -gboolean -cal_client_add_timezone (CalClient *client, icaltimezone *izone, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - const char *tzobj; - - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - g_return_val_if_fail (izone != NULL, FALSE); - - priv = client->priv; - - e_mutex_lock (priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (priv->mutex); - - /* convert icaltimezone into a string */ - tzobj = icalcomponent_as_ical_string (icaltimezone_get_component (izone)); - - /* call the backend */ - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_addTimezone (priv->cal, tzobj, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -/** - * cal_client_get_query: - * @client: A calendar client. - * @sexp: S-expression representing the query. - * - * Creates a live query object from a loaded calendar. - * - * Return value: A query object that will emit notification signals as calendar - * components are added and removed from the query in the server. - **/ -gboolean -cal_client_get_query (CalClient *client, const char *sexp, CalQuery **query, GError **error) -{ - CORBA_Environment ev; - ECalendarOp *our_op; - ECalendarStatus status; - - g_return_val_if_fail (client != NULL, E_CALENDAR_STATUS_INVALID_ARG); - g_return_val_if_fail (IS_CAL_CLIENT (client), E_CALENDAR_STATUS_INVALID_ARG); - g_return_val_if_fail (query != NULL, E_CALENDAR_STATUS_INVALID_ARG); - - e_mutex_lock (client->priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (client->priv->mutex); - - CORBA_exception_init (&ev); - - our_op->listener = query_listener_new (); - GNOME_Evolution_Calendar_Cal_getQuery (client->priv->cal, sexp, BONOBO_OBJREF (our_op->listener), &ev); - - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - *query = our_op->query; - - bonobo_object_unref (BONOBO_OBJECT (our_op->listener)); - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - - -/* This ensures that the given timezone is on the server. We use this to pass - the default timezone to the server, so it can resolve DATE and floating - DATE-TIME values into specific times. (Most of our IDL interface uses - time_t values to pass specific times from the server to the client.) */ -static gboolean -cal_client_ensure_timezone_on_server (CalClient *client, icaltimezone *zone, GError **error) -{ - CalClientPrivate *priv; - char *tzid; - icaltimezone *tmp_zone; - - priv = client->priv; - - /* FIXME This is highly broken since there is no locking */ - - /* If the zone is NULL or UTC we don't need to do anything. */ - if (!zone) - return TRUE; - - tzid = icaltimezone_get_tzid (zone); - - if (!strcmp (tzid, "UTC")) - return TRUE; - - /* See if we already have it in the cache. If we do, it must be on - the server already. */ - tmp_zone = g_hash_table_lookup (priv->timezones, tzid); - if (tmp_zone) - return TRUE; - - /* Now we have to send it to the server, in case it doesn't already - have it. */ - return cal_client_add_timezone (client, zone, error); -} - -gboolean -cal_client_set_default_timezone (CalClient *client, icaltimezone *zone, GError **error) -{ - CalClientPrivate *priv; - CORBA_Environment ev; - ECalendarStatus status; - ECalendarOp *our_op; - const char *tzid; - - g_return_val_if_fail (IS_CAL_CLIENT (client), FALSE); - g_return_val_if_fail (zone != NULL, FALSE); - - priv = client->priv; - - /* Make sure the server has the VTIMEZONE data. */ - if (!cal_client_ensure_timezone_on_server (client, zone, error)) - return FALSE; - - e_mutex_lock (priv->mutex); - - if (client->priv->load_state != CAL_CLIENT_LOAD_LOADED) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_URI_NOT_LOADED, error); - } - - if (client->priv->current_op != NULL) { - e_mutex_unlock (client->priv->mutex); - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_BUSY, error); - } - - our_op = e_calendar_new_op (client); - - e_mutex_lock (our_op->mutex); - - e_mutex_unlock (priv->mutex); - - /* FIXME Adding it to the server to change the tzid */ - tzid = icaltimezone_get_tzid (zone); - - /* call the backend */ - CORBA_exception_init (&ev); - - GNOME_Evolution_Calendar_Cal_setDefaultTimezone (priv->cal, tzid, &ev); - if (BONOBO_EX (&ev)) { - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - CORBA_exception_free (&ev); - - g_warning (G_STRLOC ": Unable to contact backend"); - - E_CALENDAR_CHECK_STATUS (E_CALENDAR_STATUS_CORBA_EXCEPTION, error); - } - - CORBA_exception_free (&ev); - - /* wait for something to happen (both cancellation and a - successful response will notity us via our cv */ - e_mutex_cond_wait (&our_op->cond, our_op->mutex); - - status = our_op->status; - - e_calendar_remove_op (client, our_op); - e_mutex_unlock (our_op->mutex); - e_calendar_free_op (our_op); - - E_CALENDAR_CHECK_STATUS (status, error); -} - -/** - * cal_client_get_error_message - * @status: A status code. - * - * Get an error message for the given status code. - * - * Returns: the error message. - */ -const char * -cal_client_get_error_message (ECalendarStatus status) -{ - switch (status) { - case E_CALENDAR_STATUS_INVALID_ARG : - return _("Invalid argument"); - case E_CALENDAR_STATUS_BUSY : - return _("Backend is busy"); - case E_CALENDAR_STATUS_REPOSITORY_OFFLINE : - return _("Repository is offline"); - case E_CALENDAR_STATUS_NO_SUCH_CALENDAR : - return _("No such calendar"); - case E_CALENDAR_STATUS_OBJECT_NOT_FOUND : - return _("Object not found"); - case E_CALENDAR_STATUS_INVALID_OBJECT : - return _("Invalid object"); - case E_CALENDAR_STATUS_URI_NOT_LOADED : - return _("URI not loaded"); - case E_CALENDAR_STATUS_URI_ALREADY_LOADED : - return _("URI already loaded"); - case E_CALENDAR_STATUS_PERMISSION_DENIED : - return _("Permission denied"); - case E_CALENDAR_STATUS_CARD_NOT_FOUND : - return _("Object not found"); - case E_CALENDAR_STATUS_CARD_ID_ALREADY_EXISTS : - return _("Object ID already exists"); - case E_CALENDAR_STATUS_PROTOCOL_NOT_SUPPORTED : - return _("Protocol not supported"); - case E_CALENDAR_STATUS_CANCELLED : - return _("Operation has been cancelled"); - case E_CALENDAR_STATUS_COULD_NOT_CANCEL : - return _("Could not cancel operation"); - case E_CALENDAR_STATUS_AUTHENTICATION_FAILED : - return _("Authentication failed"); - case E_CALENDAR_STATUS_AUTHENTICATION_REQUIRED : - return _("Authentication required"); - case E_CALENDAR_STATUS_CORBA_EXCEPTION : - return _("A CORBA esception has occurred"); - case E_CALENDAR_STATUS_OTHER_ERROR : - return _("Unknown error"); - case E_CALENDAR_STATUS_OK : - return _("No error"); - } - - return NULL; -} |