diff options
Diffstat (limited to 'calendar/pcs/cal-backend.c')
-rw-r--r-- | calendar/pcs/cal-backend.c | 767 |
1 files changed, 0 insertions, 767 deletions
diff --git a/calendar/pcs/cal-backend.c b/calendar/pcs/cal-backend.c deleted file mode 100644 index b2b16b2c9e..0000000000 --- a/calendar/pcs/cal-backend.c +++ /dev/null @@ -1,767 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* Evolution calendar - generic backend class - * - * Copyright (C) 2000 Helix Code, Inc. - * - * Authors: Federico Mena-Quintero <federico@helixcode.com> - * JP Rosevear <jpr@helixcode.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - */ - -#include <config.h> -#include <gtk/gtk.h> -#include <gnome-xml/parser.h> -#include <gnome-xml/parserInternals.h> -#include <gnome-xml/xmlmemory.h> - -#include "cal-backend.h" -#include "libversit/vcc.h" - - - -/* Signal IDs */ -enum { - LAST_CLIENT_GONE, - LAST_SIGNAL -}; - -static void cal_backend_class_init (CalBackendClass *class); -static void cal_backend_init (CalBackend *backend); -static void cal_backend_destroy (GtkObject *object); -static gboolean cal_backend_log_sync (CalBackend *backend); -static GHashTable *cal_backend_get_log_entries (CalBackend *backend, - CalObjType type, - time_t since); - -static GtkObjectClass *parent_class; - -static guint cal_backend_signals[LAST_SIGNAL]; - -#define CLASS(backend) (CAL_BACKEND_CLASS (GTK_OBJECT (backend)->klass)) - - - -/** - * cal_backend_get_type: - * @void: - * - * Registers the #CalBackend class if necessary, and returns the type ID - * associated to it. - * - * Return value: The type ID of the #CalBackend class. - **/ -GtkType -cal_backend_get_type (void) -{ - static GtkType cal_backend_type = 0; - - if (!cal_backend_type) { - static const GtkTypeInfo cal_backend_info = { - "CalBackend", - sizeof (CalBackend), - sizeof (CalBackendClass), - (GtkClassInitFunc) cal_backend_class_init, - (GtkObjectInitFunc) cal_backend_init, - NULL, /* reserved_1 */ - NULL, /* reserved_2 */ - (GtkClassInitFunc) NULL - }; - - cal_backend_type = - gtk_type_unique (GTK_TYPE_OBJECT, &cal_backend_info); - } - - return cal_backend_type; -} - -/* Class initialization function for the calendar backend */ -static void -cal_backend_class_init (CalBackendClass *class) -{ - GtkObjectClass *object_class; - - object_class = (GtkObjectClass *) class; - - parent_class = gtk_type_class (GTK_TYPE_OBJECT); - - object_class->destroy = cal_backend_destroy; - - cal_backend_signals[LAST_CLIENT_GONE] = - gtk_signal_new ("last_client_gone", - GTK_RUN_FIRST, - object_class->type, - GTK_SIGNAL_OFFSET (CalBackendClass, last_client_gone), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); - - gtk_object_class_add_signals (object_class, cal_backend_signals, LAST_SIGNAL); -} - -/* Per instance initialization function */ -static void -cal_backend_init (CalBackend *backend) -{ - backend->uri = NULL; - backend->entries = NULL; - backend->timer = -1; -} - -static void -cal_backend_destroy (GtkObject *object) -{ - CalBackend *backend; - - g_return_if_fail (object != NULL); - g_return_if_fail (IS_CAL_BACKEND (object)); - - backend = CAL_BACKEND (object); - - if (backend->timer != -1) { - gtk_timeout_remove (backend->timer); - backend->timer = -1; - } - - if (backend->uri) { - cal_backend_log_sync (backend); - gnome_vfs_uri_unref (backend->uri); - } - - if (GTK_OBJECT_CLASS (parent_class)->destroy) - (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); -} - - - -/** - * cal_backend_get_uri: - * @backend: A calendar backend. - * - * Queries the URI of a calendar backend, which must already have a loaded - * calendar. - * - * Return value: The URI where the calendar is stored. - **/ -GnomeVFSURI * -cal_backend_get_uri (CalBackend *backend) -{ - g_return_val_if_fail (backend != NULL, NULL); - g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); - - g_assert (CLASS (backend)->get_uri != NULL); - return (* CLASS (backend)->get_uri) (backend); -} - -static void -cal_backend_set_uri (CalBackend *backend, GnomeVFSURI *uri) -{ - if (backend->uri) - gnome_vfs_uri_unref (backend->uri); - - if (backend->timer != -1) - gtk_timeout_remove (backend->timer); - - - gnome_vfs_uri_ref (uri); - backend->uri = uri; - backend->timer = gtk_timeout_add (60000, - (GtkFunction)cal_backend_log_sync, - backend); -} - -/** - * cal_backend_add_cal: - * @backend: A calendar backend. - * @cal: A calendar client interface object. - * - * Adds a calendar client interface object to a calendar @backend. - * The calendar backend must already have a loaded calendar. - **/ -void -cal_backend_add_cal (CalBackend *backend, Cal *cal) -{ - g_return_if_fail (backend != NULL); - g_return_if_fail (IS_CAL_BACKEND (backend)); - - g_assert (CLASS (backend)->add_cal != NULL); - (* CLASS (backend)->add_cal) (backend, cal); -} - -/** - * cal_backend_load: - * @backend: A calendar backend. - * @uri: URI that contains the calendar data. - * - * Loads a calendar backend with data from a calendar stored at the specified - * URI. - * - * Return value: An operation status code. - **/ -CalBackendLoadStatus -cal_backend_load (CalBackend *backend, GnomeVFSURI *uri) -{ - CalBackendLoadStatus result; - - g_return_val_if_fail (backend != NULL, CAL_BACKEND_LOAD_ERROR); - g_return_val_if_fail (IS_CAL_BACKEND (backend), CAL_BACKEND_LOAD_ERROR); - g_return_val_if_fail (uri != NULL, CAL_BACKEND_LOAD_ERROR); - - g_assert (CLASS (backend)->load != NULL); - result = (* CLASS (backend)->load) (backend, uri); - - /* Remember the URI for saving the log file in the same dir and add - * a timeout handler so for saving pending entries sometimes */ - if (result == CAL_BACKEND_LOAD_SUCCESS) - cal_backend_set_uri (backend, uri); - - return result; -} - -/** - * cal_backend_create: - * @backend: A calendar backend. - * @uri: URI that will contain the calendar data. - * - * Creates a new empty calendar in a calendar backend. - **/ -void -cal_backend_create (CalBackend *backend, GnomeVFSURI *uri) -{ - g_return_if_fail (backend != NULL); - g_return_if_fail (IS_CAL_BACKEND (backend)); - g_return_if_fail (uri != NULL); - - g_assert (CLASS (backend)->create != NULL); - (* CLASS (backend)->create) (backend, uri); - - /* Remember the URI for saving the log file in the same dir and add - * a timeout handler so for saving pending entries sometimes */ - cal_backend_set_uri (backend, uri); -} - -/** - * cal_backend_get_n_objects: - * @backend: A calendar backend. - * @type: Types of objects that will be included in the count. - * - * Queries the number of calendar objects of a particular type. - * - * Return value: Number of objects of the specified @type. - **/ -int -cal_backend_get_n_objects (CalBackend *backend, CalObjType type) -{ - g_return_val_if_fail (backend != NULL, -1); - g_return_val_if_fail (IS_CAL_BACKEND (backend), -1); - - g_assert (CLASS (backend)->get_n_objects != NULL); - return (* CLASS (backend)->get_n_objects) (backend, type); -} - -/** - * cal_backend_get_object: - * @backend: A calendar backend. - * @uid: Unique identifier for a calendar object. - * - * Queries a calendar backend for a calendar object based on its unique - * identifier. - * - * Return value: The string representation of a complete calendar wrapping the - * the sought object, or NULL if no object had the specified UID. A complete - * calendar is returned because you also need the timezone data. - **/ -char * -cal_backend_get_object (CalBackend *backend, const char *uid) -{ - g_return_val_if_fail (backend != NULL, NULL); - g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); - g_return_val_if_fail (uid != NULL, NULL); - - g_assert (CLASS (backend)->get_object != NULL); - return (* CLASS (backend)->get_object) (backend, uid); -} - -/** - * cal_backend_get_uids: - * @backend: A calendar backend. - * @type: Bitmask with types of objects to return. - * - * Builds a list of unique identifiers corresponding to calendar objects whose - * type matches one of the types specified in the @type flags. - * - * Return value: A list of strings that are the sought UIDs. The list should be - * freed using the cal_obj_uid_list_free() function. - **/ -GList * -cal_backend_get_uids (CalBackend *backend, CalObjType type) -{ - g_return_val_if_fail (backend != NULL, NULL); - g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); - - g_assert (CLASS (backend)->get_uids != NULL); - return (* CLASS (backend)->get_uids) (backend, type); -} - - -static void -cal_backend_foreach_changed (gpointer key, gpointer value, gpointer data) -{ - GList **list = data; - - *list = g_list_append (*list, value); -} - -/** - * cal_backend_get_changed_uids: - * @backend: - * @type: - * @since: - * - * - * - * Return value: - **/ -GList * -cal_backend_get_changed_uids (CalBackend *backend, CalObjType type, time_t since) -{ - GHashTable *hash; - GList *uids = NULL; - - g_return_val_if_fail (backend != NULL, NULL); - g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); - - hash = cal_backend_get_log_entries (backend, type, since); - - if (hash) - g_hash_table_foreach (hash, cal_backend_foreach_changed, &uids); - - return uids; -} - - -/** - * cal_backend_get_objects_in_range: - * @backend: A calendar backend. - * @type: Bitmask with types of objects to return. - * @start: Start time for query. - * @end: End time for query. - * - * Builds a list of unique identifiers corresponding to calendar objects of the - * specified type that occur or recur within the specified time range. - * - * Return value: A list of UID strings. The list should be freed using the - * cal_obj_uid_list_free() function. - **/ -GList * -cal_backend_get_objects_in_range (CalBackend *backend, CalObjType type, - time_t start, time_t end) -{ - g_return_val_if_fail (backend != NULL, NULL); - g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); - g_return_val_if_fail (start != -1 && end != -1, NULL); - g_return_val_if_fail (start <= end, NULL); - - g_assert (CLASS (backend)->get_objects_in_range != NULL); - return (* CLASS (backend)->get_objects_in_range) (backend, type, start, end); -} - -/** - * cal_backend_get_alarms_in_range: - * @backend: A calendar backend. - * @start: Start time for query. - * @end: End time for query. - * - * Builds a sorted list of the alarms that trigger in the specified time range. - * - * Return value: A list of #CalAlarmInstance structures, sorted by trigger time. - **/ -GList * -cal_backend_get_alarms_in_range (CalBackend *backend, time_t start, time_t end) -{ - g_return_val_if_fail (backend != NULL, NULL); - g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); - g_return_val_if_fail (start != -1 && end != -1, NULL); - g_return_val_if_fail (start <= end, NULL); - - g_assert (CLASS (backend)->get_alarms_in_range != NULL); - return (* CLASS (backend)->get_alarms_in_range) (backend, start, end); -} - -/** - * cal_backend_get_alarms_for_object: - * @backend: A calendar backend. - * @uid: Unique identifier for a calendar object. - * @start: Start time for query. - * @end: End time for query. - * @alarms: Return value for the list of alarm instances. - * - * Builds a sorted list of the alarms of the specified event that trigger in a - * particular time range. - * - * Return value: TRUE on success, FALSE if the object was not found. - **/ -gboolean -cal_backend_get_alarms_for_object (CalBackend *backend, const char *uid, - time_t start, time_t end, - GList **alarms) -{ - g_return_val_if_fail (backend != NULL, FALSE); - g_return_val_if_fail (IS_CAL_BACKEND (backend), 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); - - g_assert (CLASS (backend)->get_alarms_for_object != NULL); - return (* CLASS (backend)->get_alarms_for_object) (backend, uid, start, end, alarms); -} - -/* Internal logging stuff */ -typedef enum { - CAL_BACKEND_UPDATED, - CAL_BACKEND_REMOVED -} CalBackendLogEntryType; - -typedef struct { - char *uid; - CalObjType type; - - CalBackendLogEntryType event_type; - - time_t time_stamp; -} CalBackendLogEntry; - -typedef struct { - CalObjType type; - time_t since; - - gboolean in_valid_timestamp; - - GHashTable *hash; -} CalBackendParseState; - -static gchar * -cal_backend_log_name (GnomeVFSURI *uri) -{ - const gchar *path; - gchar *filename; - - path = gnome_vfs_uri_get_path (uri); - filename = g_strdup_printf ("%s.log.xml", path); - - return filename; -} - -static void -cal_backend_set_node_timet (xmlNodePtr node, const char *name, time_t t) -{ - char *tstring; - - tstring = g_strdup_printf ("%ld", t); - xmlSetProp (node, name, tstring); -} - -static void -cal_backend_log_entry (CalBackend *backend, - const char *uid, - CalObjType cot, - CalBackendLogEntryType type) -{ - CalBackendLogEntry *entry = g_new0 (CalBackendLogEntry, 1); - - g_assert (CLASS (backend)->get_type_by_uid != NULL); - - /* Only log todos and events */ - if (cot != CALOBJ_TYPE_EVENT && cot != CALOBJ_TYPE_TODO) - return; - - entry = g_new0 (CalBackendLogEntry, 1); - entry->uid = g_strdup (uid); - entry->type = cot; - entry->event_type = type; - entry->time_stamp = time (NULL); - - /* Append so they get stored in chronological order */ - backend->entries = g_slist_append (backend->entries, entry); -} - -static gboolean -cal_backend_log_sync (CalBackend *backend) -{ - xmlDocPtr doc; - xmlNodePtr tnode; - gchar *filename; - GSList *l; - int ret; - time_t start_time = (time_t) - 1; - time_t end_time = (time_t) - 1; - - g_return_val_if_fail (backend->uri != NULL, FALSE); - - if (backend->entries == NULL) - return TRUE; - - filename = cal_backend_log_name (backend->uri); - - doc = xmlParseFile (filename); - if (doc == NULL) { - /* Create the document */ - doc = xmlNewDoc ("1.0"); - if (doc == NULL) { - g_warning ("Log file could not be created\n"); - return FALSE; - } - - - doc->root = xmlNewDocNode(doc, NULL, "CalendarLog", NULL); - } - - tnode = xmlNewChild (doc->root, NULL, "timestamp", NULL); - for (l = backend->entries; l != NULL; l = l->next) { - xmlNodePtr node; - CalBackendLogEntry *entry; - - entry = (CalBackendLogEntry *)l->data; - node = xmlNewChild (tnode, NULL, "status", NULL); - - xmlSetProp (node, "uid", entry->uid); - - switch (entry->type) { - case CALOBJ_TYPE_EVENT: - xmlSetProp (node, "type", "event"); - break; - case CALOBJ_TYPE_TODO: - xmlSetProp (node, "type", "todo"); - break; - default: - } - - switch (entry->event_type) { - case (CAL_BACKEND_UPDATED): - xmlSetProp (node, "operation", "updated"); - break; - case (CAL_BACKEND_REMOVED): - xmlSetProp (node, "operation", "removed"); - break; - } - - if (start_time == (time_t) - 1 - || entry->time_stamp < start_time) - start_time = entry->time_stamp; - - if (end_time == (time_t) - 1 - || entry->time_stamp > end_time) - end_time = entry->time_stamp; - - g_free (entry); - } - cal_backend_set_node_timet (tnode, "start", start_time); - cal_backend_set_node_timet (tnode, "end", end_time); - - g_slist_free (backend->entries); - backend->entries = NULL; - - /* Write the file */ - xmlSetDocCompressMode (doc, 0); - ret = xmlSaveFile (filename, doc); - if (ret < 0) { - g_warning ("Log file could not be saved\n"); - return FALSE; - } - - xmlFreeDoc (doc); - - g_free (filename); - - return TRUE; -} - -static void -cal_backend_log_sax_start_element (CalBackendParseState *state, const CHAR *name, - const CHAR **attrs) -{ - if (!strcmp (name, "timestamp")) { - while (attrs && *attrs != NULL) { - const xmlChar **val = attrs; - - val++; - if (!strcmp (*attrs, "start")) { - time_t start = (time_t)strtoul (*val, NULL, 0); - - if (start >= state->since) - state->in_valid_timestamp = TRUE; - break; - } - attrs = ++val; - } - } - - if (state->in_valid_timestamp && !strcmp (name, "status")) { - CalObjChange *coc = g_new0 (CalObjChange, 1); - CalObjType cot = 0; - - while (attrs && *attrs != NULL) { - const xmlChar **val = attrs; - - - val++; - if (!strcmp (*attrs, "uid")) - coc->uid = g_strdup (*val); - - if (!strcmp (*attrs, "type")) { - if (!strcmp (*val, "event")) - cot = CALOBJ_TYPE_EVENT; - else if (!strcmp (*val, "todo")) - cot = CALOBJ_TYPE_TODO; - } - - if (!strcmp (*attrs, "operation")) { - if (!strcmp (*val, "updated")) - coc->type = CALOBJ_UPDATED; - else if (!strcmp (*val, "removed")) - coc->type = CALOBJ_REMOVED; - } - - attrs = ++val; - } - - if (state->type == CALOBJ_TYPE_ANY || state->type == cot) - g_hash_table_insert (state->hash, coc->uid, coc); - } -} - -static void -cal_backend_log_sax_end_element (CalBackendParseState *state, const CHAR *name) -{ - if (!strcmp (name, "timestamp")) { - state->in_valid_timestamp = FALSE; - } -} - -static GHashTable * -cal_backend_get_log_entries (CalBackend *backend, CalObjType type, time_t since) -{ - xmlSAXHandler handler; - CalBackendParseState state; - GHashTable *hash; - char *filename; - - g_return_val_if_fail (backend != NULL, NULL); - g_return_val_if_fail (backend->uri != NULL, NULL); - g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL); - - if (!cal_backend_log_sync (backend)) - return NULL; - - memset (&handler, 0, sizeof (xmlSAXHandler)); - handler.startElement = (startElementSAXFunc)cal_backend_log_sax_start_element; - handler.endElement = (endElementSAXFunc)cal_backend_log_sax_end_element; - - hash = g_hash_table_new (g_str_hash, g_str_equal); - - state.type = type; - state.since = since; - state.in_valid_timestamp = FALSE; - state.hash = hash; - - filename = cal_backend_log_name (backend->uri); - if (xmlSAXUserParseFile (&handler, &state, filename) < 0) - return NULL; - - return hash; -} - -/** - * cal_backend_update_object: - * @backend: A calendar backend. - * @uid: Unique identifier of the object to update. - * @calobj: String representation of the new calendar object. - * - * Updates an object in a calendar backend. It will replace any existing - * object that has the same UID as the specified one. The backend will in - * turn notify all of its clients about the change. - * - * Return value: TRUE on success, FALSE on being passed an invalid object or one - * with an unsupported type. - **/ -gboolean -cal_backend_update_object (CalBackend *backend, const char *uid, const char *calobj) -{ - CalObjType cot; - gboolean result; - - g_return_val_if_fail (backend != NULL, FALSE); - g_return_val_if_fail (IS_CAL_BACKEND (backend), FALSE); - g_return_val_if_fail (uid != NULL, FALSE); - g_return_val_if_fail (calobj != NULL, FALSE); - - g_assert (CLASS (backend)->update_object != NULL); - result = (* CLASS (backend)->update_object) (backend, uid, calobj); - - if (result) { - cot = (* CLASS (backend)->get_type_by_uid) (backend, uid); - cal_backend_log_entry (backend, uid, cot, CAL_BACKEND_UPDATED); - } - - return result; -} - -/** - * cal_backend_remove_object: - * @backend: A calendar backend. - * @uid: Unique identifier of the object to remove. - * - * Removes an object in a calendar backend. The backend will notify all of its - * clients about the change. - * - * Return value: TRUE on success, FALSE on being passed an UID for an object - * that does not exist in the backend. - **/ -gboolean -cal_backend_remove_object (CalBackend *backend, const char *uid) -{ - CalObjType cot; - gboolean result; - - g_return_val_if_fail (backend != NULL, FALSE); - g_return_val_if_fail (IS_CAL_BACKEND (backend), FALSE); - g_return_val_if_fail (uid != NULL, FALSE); - - g_assert (CLASS (backend)->remove_object != NULL); - cot = (* CLASS (backend)->get_type_by_uid) (backend, uid); - result = (* CLASS (backend)->remove_object) (backend, uid); - - if (result) - cal_backend_log_entry (backend, uid, cot, CAL_BACKEND_REMOVED); - - return result; -} - -/** - * cal_backend_last_client_gone: - * @backend: A calendar backend. - * - * Emits the "last_client_gone" signal of a calendar backend. This function is - * to be used only by backend implementations. - **/ -void -cal_backend_last_client_gone (CalBackend *backend) -{ - g_return_if_fail (backend != NULL); - g_return_if_fail (IS_CAL_BACKEND (backend)); - - gtk_signal_emit (GTK_OBJECT (backend), cal_backend_signals[LAST_CLIENT_GONE]); -} - |