aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/pcs/cal-backend-file.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/pcs/cal-backend-file.c')
-rw-r--r--calendar/pcs/cal-backend-file.c1644
1 files changed, 782 insertions, 862 deletions
diff --git a/calendar/pcs/cal-backend-file.c b/calendar/pcs/cal-backend-file.c
index b26f2fd74c..e5e3abb7c9 100644
--- a/calendar/pcs/cal-backend-file.c
+++ b/calendar/pcs/cal-backend-file.c
@@ -1,7 +1,6 @@
/* Evolution calendar - iCalendar file backend
*
- * Copyright (C) 2000 Ximian, Inc.
- * Copyright (C) 2000 Ximian, Inc.
+ * Copyright (C) 2000-2003 Ximian, Inc.
*
* Authors: Federico Mena-Quintero <federico@ximian.com>
* Rodrigo Moya <rodrigo@ximian.com>
@@ -27,38 +26,41 @@
#include <bonobo/bonobo-moniker-util.h>
#include <libgnome/gnome-i18n.h>
#include <libgnomevfs/gnome-vfs.h>
-#include "e-util/e-dbhash.h"
+#include "e-util/e-xml-hash-utils.h"
#include "cal-util/cal-recur.h"
#include "cal-util/cal-util.h"
-#include "cal-backend-file.h"
+#include "cal-backend-file-events.h"
#include "cal-backend-util.h"
+#include "cal-backend-object-sexp.h"
+/* Placeholder for each component and its recurrences */
+typedef struct {
+ CalComponent *full_object;
+ GHashTable *recurrences;
+} CalBackendFileObject;
+
/* Private part of the CalBackendFile structure */
struct _CalBackendFilePrivate {
/* URI where the calendar data is stored */
char *uri;
+ /* Filename in the dir */
+ char *file_name;
+
/* Toplevel VCALENDAR component */
icalcomponent *icalcomp;
- /* All the CalComponent objects in the calendar, hashed by UID. The
+ /* All the objects in the calendar, hashed by UID. The
* hash key *is* the uid returned by cal_component_get_uid(); it is not
* copied, so don't free it when you remove an object from the hash
- * table.
+ * table. Each item in the hash table is a CalBackendFileObject.
*/
GHashTable *comp_uid_hash;
- /* All event, to-do, and journal components in the calendar; they are
- * here just for easy access (i.e. so that you don't have to iterate
- * over the comp_uid_hash). If you need *all* the components in the
- * calendar, iterate over the hash instead.
- */
- GList *events;
- GList *todos;
- GList *journals;
-
+ GList *comp;
+
/* Config database handle for free/busy organizer information */
EConfigListener *config_listener;
@@ -68,181 +70,29 @@ struct _CalBackendFilePrivate {
/* The calendar's default timezone, used for resolving DATE and
floating DATE-TIME values. */
icaltimezone *default_zone;
+
+ /* The list of live queries */
+ GList *queries;
};
-static void cal_backend_file_class_init (CalBackendFileClass *class);
-static void cal_backend_file_init (CalBackendFile *cbfile, CalBackendFileClass *class);
static void cal_backend_file_dispose (GObject *object);
static void cal_backend_file_finalize (GObject *object);
-static const char *cal_backend_file_get_uri (CalBackend *backend);
-static gboolean cal_backend_file_is_read_only (CalBackend *backend);
-static const char *cal_backend_file_get_cal_address (CalBackend *backend);
-static const char *cal_backend_file_get_alarm_email_address (CalBackend *backend);
-static const char *cal_backend_file_get_ldap_attribute (CalBackend *backend);
-static const char *cal_backend_file_get_static_capabilities (CalBackend *backend);
-static CalBackendOpenStatus cal_backend_file_open (CalBackend *backend,
- const char *uristr,
- gboolean only_if_exists);
-static gboolean cal_backend_file_is_loaded (CalBackend *backend);
-static Query *cal_backend_file_get_query (CalBackend *backend,
- GNOME_Evolution_Calendar_QueryListener ql,
- const char *sexp);
-
-static CalMode cal_backend_file_get_mode (CalBackend *backend);
-static void cal_backend_file_set_mode (CalBackend *backend, CalMode mode);
-
-static int cal_backend_file_get_n_objects (CalBackend *backend, CalObjType type);
-static char *cal_backend_file_get_default_object (CalBackend *backend, CalObjType type);
-static CalComponent *cal_backend_file_get_object_component (CalBackend *backend, const char *uid);
-static char *cal_backend_file_get_timezone_object (CalBackend *backend, const char *tzid);
-static GList *cal_backend_file_get_uids (CalBackend *backend, CalObjType type);
-static GList *cal_backend_file_get_objects_in_range (CalBackend *backend, CalObjType type,
- time_t start, time_t end);
-static GList *cal_backend_file_get_free_busy (CalBackend *backend, GList *users, time_t start, time_t end);
-static GNOME_Evolution_Calendar_CalObjChangeSeq *cal_backend_file_get_changes (
- CalBackend *backend, CalObjType type, const char *change_id);
-
-static GNOME_Evolution_Calendar_CalComponentAlarmsSeq *cal_backend_file_get_alarms_in_range (
- CalBackend *backend, time_t start, time_t end);
-
-static GNOME_Evolution_Calendar_CalComponentAlarms *cal_backend_file_get_alarms_for_object (
- CalBackend *backend, const char *uid,
- time_t start, time_t end, gboolean *object_found);
-
-static CalBackendResult cal_backend_file_discard_alarm (CalBackend *backend,
- const char *uid,
- const char *auid);
-
-static CalBackendResult cal_backend_file_update_objects (CalBackend *backend,
- const char *calobj,
- CalObjModType mod);
-static CalBackendResult cal_backend_file_remove_object (CalBackend *backend, const char *uid, CalObjModType mod);
-
-static CalBackendSendResult cal_backend_file_send_object (CalBackend *backend,
- const char *calobj, gchar **new_calobj,
- GNOME_Evolution_Calendar_UserList **user_list,
- char error_msg[256]);
-
-static icaltimezone* cal_backend_file_get_timezone (CalBackend *backend, const char *tzid);
-static icaltimezone* cal_backend_file_get_default_timezone (CalBackend *backend);
-static gboolean cal_backend_file_set_default_timezone (CalBackend *backend,
- const char *tzid);
-
-static CalBackendClass *parent_class;
+static CalBackendSyncClass *parent_class;
-/**
- * cal_backend_file_get_type:
- * @void:
- *
- * Registers the #CalBackendFile class if necessary, and returns the type ID
- * associated to it.
- *
- * Return value: The type ID of the #CalBackendFile class.
- **/
-GType
-cal_backend_file_get_type (void)
-{
- static GType cal_backend_file_type = 0;
-
- if (!cal_backend_file_type) {
- static GTypeInfo info = {
- sizeof (CalBackendFileClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) cal_backend_file_class_init,
- NULL, NULL,
- sizeof (CalBackendFile),
- 0,
- (GInstanceInitFunc) cal_backend_file_init
- };
- cal_backend_file_type = g_type_register_static (CAL_BACKEND_TYPE,
- "CalBackendFile", &info, 0);
- }
-
- return cal_backend_file_type;
-}
-
-/* Class initialization function for the file backend */
-static void
-cal_backend_file_class_init (CalBackendFileClass *class)
-{
- GObjectClass *object_class;
- CalBackendClass *backend_class;
-
- object_class = (GObjectClass *) class;
- backend_class = (CalBackendClass *) class;
-
- parent_class = (CalBackendClass *) g_type_class_peek_parent (class);
-
- object_class->dispose = cal_backend_file_dispose;
- object_class->finalize = cal_backend_file_finalize;
-
- backend_class->get_uri = cal_backend_file_get_uri;
- backend_class->is_read_only = cal_backend_file_is_read_only;
- backend_class->get_cal_address = cal_backend_file_get_cal_address;
- backend_class->get_alarm_email_address = cal_backend_file_get_alarm_email_address;
- backend_class->get_ldap_attribute = cal_backend_file_get_ldap_attribute;
- backend_class->get_static_capabilities = cal_backend_file_get_static_capabilities;
- backend_class->open = cal_backend_file_open;
- backend_class->is_loaded = cal_backend_file_is_loaded;
- backend_class->get_query = cal_backend_file_get_query;
- backend_class->get_mode = cal_backend_file_get_mode;
- backend_class->set_mode = cal_backend_file_set_mode;
- backend_class->get_n_objects = cal_backend_file_get_n_objects;
- backend_class->get_default_object = cal_backend_file_get_default_object;
- backend_class->get_object_component = cal_backend_file_get_object_component;
- backend_class->get_timezone_object = cal_backend_file_get_timezone_object;
- backend_class->get_uids = cal_backend_file_get_uids;
- backend_class->get_objects_in_range = cal_backend_file_get_objects_in_range;
- backend_class->get_free_busy = cal_backend_file_get_free_busy;
- backend_class->get_changes = cal_backend_file_get_changes;
- backend_class->get_alarms_in_range = cal_backend_file_get_alarms_in_range;
- backend_class->get_alarms_for_object = cal_backend_file_get_alarms_for_object;
- backend_class->discard_alarm = cal_backend_file_discard_alarm;
- backend_class->update_objects = cal_backend_file_update_objects;
- backend_class->remove_object = cal_backend_file_remove_object;
- backend_class->send_object = cal_backend_file_send_object;
-
- backend_class->get_timezone = cal_backend_file_get_timezone;
- backend_class->get_default_timezone = cal_backend_file_get_default_timezone;
- backend_class->set_default_timezone = cal_backend_file_set_default_timezone;
-}
-
-/* Object initialization function for the file backend */
-static void
-cal_backend_file_init (CalBackendFile *cbfile, CalBackendFileClass *class)
-{
- CalBackendFilePrivate *priv;
-
- priv = g_new0 (CalBackendFilePrivate, 1);
- cbfile->priv = priv;
-
- priv->uri = NULL;
- priv->icalcomp = NULL;
- priv->comp_uid_hash = NULL;
- priv->events = NULL;
- priv->todos = NULL;
- priv->journals = NULL;
-
- /* The timezone defaults to UTC. */
- priv->default_zone = icaltimezone_get_utc_timezone ();
-
- priv->config_listener = e_config_listener_new ();
-}
-
/* g_hash_table_foreach() callback to destroy a CalComponent */
static void
-free_cal_component (gpointer key, gpointer value, gpointer data)
+free_object (gpointer key, gpointer value, gpointer data)
{
- CalComponent *comp;
+ CalBackendFileObject *obj_data = value;
- comp = CAL_COMPONENT (value);
- g_object_unref (comp);
+ g_object_unref (obj_data->full_object);
+ g_hash_table_foreach (obj_data->recurrences, (GHFunc) g_object_unref, NULL);
+ g_hash_table_destroy (obj_data->recurrences);
}
/* Saves the calendar data */
@@ -340,18 +190,13 @@ cal_backend_file_dispose (GObject *object)
}
if (priv->comp_uid_hash) {
- g_hash_table_foreach (priv->comp_uid_hash,
- free_cal_component, NULL);
+ g_hash_table_foreach (priv->comp_uid_hash, (GHFunc) free_object, NULL);
g_hash_table_destroy (priv->comp_uid_hash);
priv->comp_uid_hash = NULL;
}
- g_list_free (priv->events);
- g_list_free (priv->todos);
- g_list_free (priv->journals);
- priv->events = NULL;
- priv->todos = NULL;
- priv->journals = NULL;
+ g_list_free (priv->comp);
+ priv->comp = NULL;
if (priv->icalcomp) {
icalcomponent_free (priv->icalcomp);
@@ -401,72 +246,80 @@ static CalComponent *
lookup_component (CalBackendFile *cbfile, const char *uid)
{
CalBackendFilePrivate *priv;
- CalComponent *comp;
+ CalBackendFileObject *obj_data;
priv = cbfile->priv;
- comp = g_hash_table_lookup (priv->comp_uid_hash, uid);
-
- return comp;
+ /* FIXME: search recurrences also */
+ obj_data = g_hash_table_lookup (priv->comp_uid_hash, uid);
+ return obj_data ? obj_data->full_object : NULL;
}
/* Calendar backend methods */
-/* Get_uri handler for the file backend */
-static const char *
-cal_backend_file_get_uri (CalBackend *backend)
-{
- CalBackendFile *cbfile;
- CalBackendFilePrivate *priv;
-
- cbfile = CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
-
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
- g_assert (priv->uri != NULL);
-
- return (const char *) priv->uri;
-}
-
/* Is_read_only handler for the file backend */
-static gboolean
-cal_backend_file_is_read_only (CalBackend *backend)
+static CalBackendSyncStatus
+cal_backend_file_is_read_only (CalBackendSync *backend, Cal *cal, gboolean *read_only)
{
/* we just return FALSE, since all calendars are read-write */
- return FALSE;
+ *read_only = FALSE;
+
+ return GNOME_Evolution_Calendar_Success;
}
/* Get_email_address handler for the file backend */
-static const char *
-cal_backend_file_get_cal_address (CalBackend *backend)
+static CalBackendSyncStatus
+cal_backend_file_get_cal_address (CalBackendSync *backend, Cal *cal, char **address)
{
/* A file backend has no particular email address associated
* with it (although that would be a useful feature some day).
*/
- return NULL;
+ *address = NULL;
+
+ return GNOME_Evolution_Calendar_Success;
}
-static const char *
-cal_backend_file_get_ldap_attribute (CalBackend *backend)
+static CalBackendSyncStatus
+cal_backend_file_get_ldap_attribute (CalBackendSync *backend, Cal *cal, char **attribute)
{
- return NULL;
+ *attribute = NULL;
+
+ return GNOME_Evolution_Calendar_Success;
}
-static const char *
-cal_backend_file_get_alarm_email_address (CalBackend *backend)
+static CalBackendSyncStatus
+cal_backend_file_get_alarm_email_address (CalBackendSync *backend, Cal *cal, char **address)
{
/* A file backend has no particular email address associated
* with it (although that would be a useful feature some day).
*/
- return NULL;
+ *address = NULL;
+
+ return GNOME_Evolution_Calendar_Success;
}
-static const char *
-cal_backend_file_get_static_capabilities (CalBackend *backend)
+static CalBackendSyncStatus
+cal_backend_file_get_static_capabilities (CalBackendSync *backend, Cal *cal, char **capabilities)
{
- return CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS;
+ *capabilities = CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS;
+
+ return GNOME_Evolution_Calendar_Success;
+}
+
+/* function to resolve timezones */
+static icaltimezone *
+resolve_tzid (const char *tzid, gpointer user_data)
+{
+ icalcomponent *vcalendar_comp = user_data;
+
+ if (!tzid || !tzid[0])
+ return NULL;
+ else if (!strcmp (tzid, "UTC"))
+ return icaltimezone_get_utc_timezone ();
+
+ return icalcomponent_get_timezone (vcalendar_comp, tzid);
}
/* Idle handler; we save the calendar since it is dirty */
@@ -506,7 +359,7 @@ static void
check_dup_uid (CalBackendFile *cbfile, CalComponent *comp)
{
CalBackendFilePrivate *priv;
- CalComponent *old_comp;
+ CalBackendFileObject *obj_data;
const char *uid;
char *new_uid;
@@ -514,8 +367,8 @@ check_dup_uid (CalBackendFile *cbfile, CalComponent *comp)
cal_component_get_uid (comp, &uid);
- old_comp = g_hash_table_lookup (priv->comp_uid_hash, uid);
- if (!old_comp)
+ obj_data = g_hash_table_lookup (priv->comp_uid_hash, uid);
+ if (!obj_data)
return; /* Everything is fine */
g_message ("check_dup_uid(): Got object with duplicated UID `%s', changing it...", uid);
@@ -531,6 +384,22 @@ check_dup_uid (CalBackendFile *cbfile, CalComponent *comp)
mark_dirty (cbfile);
}
+static char *
+get_rid_string (CalComponent *comp)
+{
+ CalComponentRange range;
+ struct icaltimetype tt;
+
+ cal_component_get_recurid (comp, &range);
+ if (!range.datetime.value)
+ return "0";
+ tt = *range.datetime.value;
+ cal_component_free_range (&range);
+
+ return icaltime_is_valid_time (tt) && !icaltime_is_null_time (tt) ?
+ icaltime_as_ical_string (tt) : "0";
+}
+
/* Tries to add an icalcomponent to the file backend. We only store the objects
* of the types we support; all others just remain in the toplevel component so
* that we don't lose them.
@@ -539,38 +408,27 @@ static void
add_component (CalBackendFile *cbfile, CalComponent *comp, gboolean add_to_toplevel)
{
CalBackendFilePrivate *priv;
- GList **list;
+ CalBackendFileObject *obj_data;
const char *uid;
GSList *categories;
priv = cbfile->priv;
- switch (cal_component_get_vtype (comp)) {
- case CAL_COMPONENT_EVENT:
- list = &priv->events;
- break;
-
- case CAL_COMPONENT_TODO:
- list = &priv->todos;
- break;
-
- case CAL_COMPONENT_JOURNAL:
- list = &priv->journals;
- break;
-
- default:
- g_assert_not_reached ();
- return;
- }
+ /* FIXME: check if it's an instance */
/* Ensure that the UID is unique; some broken implementations spit
* components with duplicated UIDs.
*/
check_dup_uid (cbfile, comp);
cal_component_get_uid (comp, &uid);
- g_hash_table_insert (priv->comp_uid_hash, (char *)uid, comp);
- *list = g_list_prepend (*list, comp);
+ obj_data = g_new0 (CalBackendFileObject, 1);
+ obj_data->full_object = comp;
+ obj_data->recurrences = g_hash_table_new (g_str_hash, g_str_equal);
+
+ g_hash_table_insert (priv->comp_uid_hash, (gpointer) uid, obj_data);
+
+ priv->comp = g_list_prepend (priv->comp, comp);
/* Put the object in the toplevel component if required */
@@ -599,8 +457,9 @@ remove_component (CalBackendFile *cbfile, CalComponent *comp)
CalBackendFilePrivate *priv;
icalcomponent *icalcomp;
const char *uid;
- GList **list, *l;
+ GList *l;
GSList *categories;
+ CalBackendFileObject *obj_data;
priv = cbfile->priv;
@@ -614,39 +473,22 @@ remove_component (CalBackendFile *cbfile, CalComponent *comp)
/* Remove it from our mapping */
cal_component_get_uid (comp, &uid);
+ obj_data = g_hash_table_lookup (priv->comp_uid_hash, uid);
+ if (!obj_data)
+ return;
+
g_hash_table_remove (priv->comp_uid_hash, uid);
-
- switch (cal_component_get_vtype (comp)) {
- case CAL_COMPONENT_EVENT:
- list = &priv->events;
- break;
-
- case CAL_COMPONENT_TODO:
- list = &priv->todos;
- break;
-
- case CAL_COMPONENT_JOURNAL:
- list = &priv->journals;
- break;
-
- default:
- /* Make the compiler shut up. */
- list = NULL;
- g_assert_not_reached ();
- }
- l = g_list_find (*list, comp);
+ l = g_list_find (priv->comp, comp);
g_assert (l != NULL);
-
- *list = g_list_remove_link (*list, l);
- g_list_free_1 (l);
+ priv->comp = g_list_delete_link (priv->comp, l);
/* Update the set of categories */
cal_component_get_categories_list (comp, &categories);
cal_backend_unref_categories (CAL_BACKEND (cbfile), categories);
cal_component_free_categories_list (categories);
- g_object_unref (comp);
+ free_object (uid, obj_data, NULL);
}
/* Scans the toplevel VCALENDAR component and stores the objects it finds */
@@ -686,7 +528,7 @@ scan_vcalendar (CalBackendFile *cbfile)
}
/* Parses an open iCalendar file and loads it into the backend */
-static CalBackendOpenStatus
+static CalBackendSyncStatus
open_cal (CalBackendFile *cbfile, const char *uristr)
{
CalBackendFilePrivate *priv;
@@ -696,7 +538,7 @@ open_cal (CalBackendFile *cbfile, const char *uristr)
icalcomp = cal_util_parse_ics_file (uristr);
if (!icalcomp)
- return CAL_BACKEND_OPEN_ERROR;
+ return GNOME_Evolution_Calendar_OtherError;
/* FIXME: should we try to demangle XROOT components and
* individual components as well?
@@ -704,7 +546,8 @@ open_cal (CalBackendFile *cbfile, const char *uristr)
if (icalcomponent_isa (icalcomp) != ICAL_VCALENDAR_COMPONENT) {
icalcomponent_free (icalcomp);
- return CAL_BACKEND_OPEN_ERROR;
+
+ return GNOME_Evolution_Calendar_OtherError;
}
priv->icalcomp = icalcomp;
@@ -714,10 +557,10 @@ open_cal (CalBackendFile *cbfile, const char *uristr)
priv->uri = g_strdup (uristr);
- return CAL_BACKEND_OPEN_SUCCESS;
+ return GNOME_Evolution_Calendar_Success;
}
-static CalBackendOpenStatus
+static CalBackendSyncStatus
create_cal (CalBackendFile *cbfile, const char *uristr)
{
CalBackendFilePrivate *priv;
@@ -734,36 +577,37 @@ create_cal (CalBackendFile *cbfile, const char *uristr)
mark_dirty (cbfile);
- return CAL_BACKEND_OPEN_SUCCESS;
+ return GNOME_Evolution_Calendar_Success;
}
-/* Open handler for the file backend */
-static CalBackendOpenStatus
-cal_backend_file_open (CalBackend *backend, const char *uristr, gboolean only_if_exists)
+static char *
+get_uri_string (CalBackend *backend)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- char *str_uri;
+ const char *master_uri;
+ char *full_uri, *str_uri;
GnomeVFSURI *uri;
- CalBackendOpenStatus status;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
+
+ master_uri = cal_backend_get_uri (backend);
+ g_message (G_STRLOC ": Trying to open %s", master_uri);
+
+ /* FIXME Check the error conditions a little more elegantly here */
+ if (g_strrstr ("tasks.ics", master_uri) || g_strrstr ("calendar.ics", master_uri)) {
+ g_warning (G_STRLOC ": Existing file name %s", master_uri);
- g_return_val_if_fail (priv->icalcomp == NULL, CAL_BACKEND_OPEN_ERROR);
- g_return_val_if_fail (uristr != NULL, CAL_BACKEND_OPEN_ERROR);
-
- g_assert (priv->uri == NULL);
- g_assert (priv->comp_uid_hash == NULL);
-
- uri = gnome_vfs_uri_new (uristr);
- if (!uri)
- return CAL_BACKEND_OPEN_ERROR;
-
- if (!uri->method_string || strcmp (uri->method_string, "file")) {
- gnome_vfs_uri_unref (uri);
- return CAL_BACKEND_OPEN_ERROR;
+ return NULL;
}
+
+ full_uri = g_strdup_printf ("%s%s%s", master_uri, G_DIR_SEPARATOR_S, priv->file_name);
+ uri = gnome_vfs_uri_new (full_uri);
+ g_free (full_uri);
+
+ if (!uri)
+ return NULL;
str_uri = gnome_vfs_uri_to_string (uri,
(GNOME_VFS_URI_HIDE_USER_NAME
@@ -771,51 +615,94 @@ cal_backend_file_open (CalBackend *backend, const char *uristr, gboolean only_if
| GNOME_VFS_URI_HIDE_HOST_NAME
| GNOME_VFS_URI_HIDE_HOST_PORT
| GNOME_VFS_URI_HIDE_TOPLEVEL_METHOD));
+ gnome_vfs_uri_unref (uri);
+
if (!str_uri || !strlen (str_uri)) {
g_free (str_uri);
- gnome_vfs_uri_unref (uri);
- return CAL_BACKEND_OPEN_ERROR;
- }
+ return NULL;
+ }
+
+ return str_uri;
+}
+
+/* Open handler for the file backend */
+static CalBackendSyncStatus
+cal_backend_file_open (CalBackendSync *backend, Cal *cal, gboolean only_if_exists)
+{
+ CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
+ char *str_uri;
+ CalBackendSyncStatus status;
+
+ cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
+
+ /* Claim a succesful open if we are already open */
+ if (priv->uri && priv->comp_uid_hash)
+ return GNOME_Evolution_Calendar_Success;
+
+ str_uri = get_uri_string (CAL_BACKEND (backend));
+ if (!str_uri)
+ return GNOME_Evolution_Calendar_OtherError;
+
if (access (str_uri, R_OK) == 0)
status = open_cal (cbfile, str_uri);
else {
if (only_if_exists)
- status = CAL_BACKEND_OPEN_NOT_FOUND;
+ status = GNOME_Evolution_Calendar_NoSuchCal;
else
status = create_cal (cbfile, str_uri);
}
g_free (str_uri);
- gnome_vfs_uri_unref (uri);
return status;
}
-/* is_loaded handler for the file backend */
-static gboolean
-cal_backend_file_is_loaded (CalBackend *backend)
+static CalBackendSyncStatus
+cal_backend_file_remove (CalBackendSync *backend, Cal *cal)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
-
+ char *str_uri;
+
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- return (priv->icalcomp != NULL);
+ str_uri = get_uri_string (CAL_BACKEND (backend));
+ if (!str_uri)
+ return GNOME_Evolution_Calendar_OtherError;
+
+ if (access (str_uri, W_OK) != 0) {
+ g_free (str_uri);
+
+ return GNOME_Evolution_Calendar_PermissionDenied;
+ }
+
+ /* FIXME Remove backup file and whole directory too? */
+ if (unlink (str_uri) != 0) {
+ g_free (str_uri);
+
+ return GNOME_Evolution_Calendar_OtherError;
+ }
+
+ g_free (str_uri);
+
+ return GNOME_Evolution_Calendar_Success;
}
-/* get_query handler for the file backend */
-static Query *
-cal_backend_file_get_query (CalBackend *backend,
- GNOME_Evolution_Calendar_QueryListener ql,
- const char *sexp)
+/* is_loaded handler for the file backend */
+static gboolean
+cal_backend_file_is_loaded (CalBackend *backend)
{
CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
- return query_new (backend, ql, sexp);
+ return (priv->icalcomp != NULL);
}
/* is_remote handler for the file backend */
@@ -841,283 +728,252 @@ cal_backend_file_set_mode (CalBackend *backend, CalMode mode)
}
-/* Get_n_objects handler for the file backend */
-static int
-cal_backend_file_get_n_objects (CalBackend *backend, CalObjType type)
+static CalBackendSyncStatus
+cal_backend_file_get_default_object (CalBackendSync *backend, Cal *cal, char **object)
{
- CalBackendFile *cbfile;
- CalBackendFilePrivate *priv;
- int n;
-
- cbfile = CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
-
- g_return_val_if_fail (priv->icalcomp != NULL, -1);
-
- n = 0;
-
- if (type & CALOBJ_TYPE_EVENT)
- n += g_list_length (priv->events);
-
- if (type & CALOBJ_TYPE_TODO)
- n += g_list_length (priv->todos);
-
- if (type & CALOBJ_TYPE_JOURNAL)
- n += g_list_length (priv->journals);
-
- return n;
-}
-
-static char *
-cal_backend_file_get_default_object (CalBackend *backend, CalObjType type)
-{
- CalBackendFile *cbfile;
- CalBackendFilePrivate *priv;
CalComponent *comp;
- char *calobj;
- cbfile = CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
-
comp = cal_component_new ();
-
- switch (type) {
- case CALOBJ_TYPE_EVENT:
+
+ switch (cal_backend_get_kind (CAL_BACKEND (backend))) {
+ case ICAL_VEVENT_COMPONENT:
cal_component_set_new_vtype (comp, CAL_COMPONENT_EVENT);
break;
- case CALOBJ_TYPE_TODO:
+ case ICAL_VTODO_COMPONENT:
cal_component_set_new_vtype (comp, CAL_COMPONENT_TODO);
break;
- case CALOBJ_TYPE_JOURNAL:
+ case ICAL_VJOURNAL_COMPONENT:
cal_component_set_new_vtype (comp, CAL_COMPONENT_JOURNAL);
break;
default:
g_object_unref (comp);
- return NULL;
+ return GNOME_Evolution_Calendar_ObjectNotFound;
}
- calobj = cal_component_get_as_string (comp);
+ *object = cal_component_get_as_string (comp);
g_object_unref (comp);
- return calobj;
+ return GNOME_Evolution_Calendar_Success;
}
/* Get_object_component handler for the file backend */
-static CalComponent *
-cal_backend_file_get_object_component (CalBackend *backend, const char *uid)
+static CalBackendSyncStatus
+cal_backend_file_get_object (CalBackendSync *backend, Cal *cal, const char *uid, const char *rid, char **object)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
+ CalComponent *comp;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (uid != NULL, NULL);
-
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_InvalidObject);
+ g_return_val_if_fail (uid != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
g_assert (priv->comp_uid_hash != NULL);
- return lookup_component (cbfile, uid);
+ comp = lookup_component (cbfile, uid);
+ if (!comp)
+ return GNOME_Evolution_Calendar_ObjectNotFound;
+
+ if (rid && *rid) {
+ /* FIXME How to retrieve instance */
+ }
+
+ *object = cal_component_get_as_string (comp);
+
+ return GNOME_Evolution_Calendar_Success;
}
/* Get_timezone_object handler for the file backend */
-static char *
-cal_backend_file_get_timezone_object (CalBackend *backend, const char *tzid)
+static CalBackendSyncStatus
+cal_backend_file_get_timezone (CalBackendSync *backend, Cal *cal, const char *tzid, char **object)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
icaltimezone *zone;
icalcomponent *icalcomp;
- char *ical_string;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (tzid != NULL, NULL);
-
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
- g_assert (priv->comp_uid_hash != NULL);
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
+ g_return_val_if_fail (tzid != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
- zone = icalcomponent_get_timezone (priv->icalcomp, tzid);
- if (!zone) {
- zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
- if (!zone)
- return NULL;
+ if (!strcmp (tzid, "UTC")) {
+ zone = icaltimezone_get_utc_timezone ();
+ } else {
+ zone = icalcomponent_get_timezone (priv->icalcomp, tzid);
+ if (!zone) {
+ zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
+ if (!zone)
+ return GNOME_Evolution_Calendar_ObjectNotFound;
+ }
}
-
+
icalcomp = icaltimezone_get_component (zone);
if (!icalcomp)
- return NULL;
+ return GNOME_Evolution_Calendar_InvalidObject;
- ical_string = icalcomponent_as_ical_string (icalcomp);
- /* We dup the string; libical owns that memory. */
- if (ical_string)
- return g_strdup (ical_string);
- else
- return NULL;
-}
-
-/* Builds a list of UIDs from a list of CalComponent objects */
-static void
-build_uids_list (GList **list, GList *components)
-{
- GList *l;
-
- for (l = components; l; l = l->next) {
- CalComponent *comp;
- const char *uid;
+ *object = g_strdup (icalcomponent_as_ical_string (icalcomp));
- comp = CAL_COMPONENT (l->data);
- cal_component_get_uid (comp, &uid);
- *list = g_list_prepend (*list, g_strdup (uid));
- }
+ return GNOME_Evolution_Calendar_Success;
}
-/* Get_uids handler for the file backend */
-static GList *
-cal_backend_file_get_uids (CalBackend *backend, CalObjType type)
+/* Add_timezone handler for the file backend */
+static CalBackendSyncStatus
+cal_backend_file_add_timezone (CalBackendSync *backend, Cal *cal, const char *tzobj)
{
+ icalcomponent *tz_comp;
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- GList *list;
- cbfile = CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
-
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+ cbfile = (CalBackendFile *) backend;
- list = NULL;
+ g_return_val_if_fail (IS_CAL_BACKEND_FILE (cbfile), GNOME_Evolution_Calendar_OtherError);
+ g_return_val_if_fail (tzobj != NULL, GNOME_Evolution_Calendar_OtherError);
- if (type & CALOBJ_TYPE_EVENT)
- build_uids_list (&list, priv->events);
-
- if (type & CALOBJ_TYPE_TODO)
- build_uids_list (&list, priv->todos);
+ priv = cbfile->priv;
- if (type & CALOBJ_TYPE_JOURNAL)
- build_uids_list (&list, priv->journals);
+ tz_comp = icalparser_parse_string (tzobj);
+ if (!tz_comp)
+ return GNOME_Evolution_Calendar_InvalidObject;
- return list;
-}
+ if (icalcomponent_isa (tz_comp) == ICAL_VTIMEZONE_COMPONENT) {
+ icaltimezone *zone;
-/* function to resolve timezones */
-static icaltimezone *
-resolve_tzid (const char *tzid, gpointer user_data)
-{
- icalcomponent *vcalendar_comp = user_data;
+ zone = icaltimezone_new ();
+ icaltimezone_set_component (zone, tz_comp);
+ if (!icalcomponent_get_timezone (priv->icalcomp, icaltimezone_get_tzid (zone))) {
+ icalcomponent_add_component (priv->icalcomp, tz_comp);
+ mark_dirty (cbfile);
+ }
- if (!tzid || !tzid[0])
- return NULL;
- else if (!strcmp (tzid, "UTC"))
- return icaltimezone_get_utc_timezone ();
+ icaltimezone_free (zone, 1);
+ }
- return icalcomponent_get_timezone (vcalendar_comp, tzid);
+ return GNOME_Evolution_Calendar_Success;
}
-/* Callback used from cal_recur_generate_instances(); adds the component's UID
- * to our hash table.
- */
-static gboolean
-add_instance (CalComponent *comp, time_t start, time_t end, gpointer data)
+
+static CalBackendSyncStatus
+cal_backend_file_set_default_timezone (CalBackendSync *backend, Cal *cal, const char *tzid)
{
- GHashTable *uid_hash;
- const char *uid;
- const char *old_uid;
+ CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
+ icaltimezone *zone;
- uid_hash = data;
+ cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
- /* We only care that the component's UID is listed in the hash table;
- * that's why we only allow generation of one instance (i.e. return
- * FALSE every time).
- */
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
- cal_component_get_uid (comp, &uid);
+ /* Look up the VTIMEZONE in our icalcomponent. */
+ zone = icalcomponent_get_timezone (priv->icalcomp, tzid);
+ if (!zone)
+ return GNOME_Evolution_Calendar_ObjectNotFound;
- old_uid = g_hash_table_lookup (uid_hash, uid);
- if (old_uid)
- return FALSE;
+ /* Set the default timezone to it. */
+ priv->default_zone = zone;
- g_hash_table_insert (uid_hash, (char *) uid, NULL);
- return FALSE;
+ return GNOME_Evolution_Calendar_Success;
}
-/* Populates a hash table with the UIDs of the components that occur or recur
- * within a specific time range.
- */
+typedef struct {
+ GList *obj_list;
+ gboolean search_needed;
+ const char *query;
+ CalBackendObjectSExp *obj_sexp;
+ CalBackend *backend;
+ icaltimezone *default_zone;
+} MatchObjectData;
+
static void
-get_instances_in_range (GHashTable *uid_hash, GList *components, time_t start, time_t end, icaltimezone *default_zone)
+match_object_sexp (gpointer key, gpointer value, gpointer data)
{
- GList *l;
-
- for (l = components; l; l = l->next) {
- CalComponent *comp;
- icalcomponent *icalcomp, *vcalendar_comp;
-
- comp = CAL_COMPONENT (l->data);
+ CalBackendFileObject *obj_data = value;
+ MatchObjectData *match_data = data;
- /* Get the parent VCALENDAR component, so we can resolve
- TZIDs. */
- icalcomp = cal_component_get_icalcomponent (comp);
- vcalendar_comp = icalcomponent_get_parent (icalcomp);
- g_assert (vcalendar_comp != NULL);
-
- cal_recur_generate_instances (comp, start, end, add_instance, uid_hash, resolve_tzid, vcalendar_comp, default_zone);
+ if ((!match_data->search_needed) ||
+ (cal_backend_object_sexp_match_comp (match_data->obj_sexp, obj_data->full_object, match_data->backend))) {
+ match_data->obj_list = g_list_append (match_data->obj_list,
+ cal_component_get_as_string (obj_data->full_object));
}
}
-/* Used from g_hash_table_foreach(), adds a UID from the hash table to our list */
-static void
-add_uid_to_list (gpointer key, gpointer value, gpointer data)
+/* Get_objects_in_range handler for the file backend */
+static CalBackendSyncStatus
+cal_backend_file_get_object_list (CalBackendSync *backend, Cal *cal, const char *sexp, GList **objects)
{
- GList **list;
- const char *uid;
- char *uid_copy;
+ CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
+ MatchObjectData match_data;
+
+ cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
- list = data;
+ g_message (G_STRLOC ": Getting object list (%s)", sexp);
- uid = key;
- uid_copy = g_strdup (uid);
+ match_data.search_needed = TRUE;
+ match_data.query = sexp;
+ match_data.obj_list = NULL;
+ match_data.backend = CAL_BACKEND (backend);
+ match_data.default_zone = priv->default_zone;
- *list = g_list_prepend (*list, uid_copy);
+ if (!strcmp (sexp, "#t"))
+ match_data.search_needed = FALSE;
+
+ match_data.obj_sexp = cal_backend_object_sexp_new (sexp);
+ if (!match_data.obj_sexp)
+ return GNOME_Evolution_Calendar_InvalidQuery;
+
+ g_hash_table_foreach (priv->comp_uid_hash, (GHFunc) match_object_sexp, &match_data);
+
+ *objects = match_data.obj_list;
+
+ return GNOME_Evolution_Calendar_Success;
}
-/* Get_objects_in_range handler for the file backend */
-static GList *
-cal_backend_file_get_objects_in_range (CalBackend *backend, CalObjType type,
- time_t start, time_t end)
+/* get_query handler for the file backend */
+static void
+cal_backend_file_start_query (CalBackend *backend, Query *query)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- GList *event_list;
- GHashTable *uid_hash;
+ MatchObjectData match_data;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+ g_message (G_STRLOC ": Starting query (%s)", query_get_text (query));
- g_return_val_if_fail (start != -1 && end != -1, NULL);
- g_return_val_if_fail (start <= end, NULL);
+ /* try to match all currently existing objects */
+ match_data.search_needed = TRUE;
+ match_data.query = query_get_text (query);
+ match_data.obj_list = NULL;
+ match_data.backend = backend;
+ match_data.default_zone = priv->default_zone;
- uid_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ if (!strcmp (match_data.query, "#t"))
+ match_data.search_needed = FALSE;
- if (type & CALOBJ_TYPE_EVENT)
- get_instances_in_range (uid_hash, priv->events, start, end,
- priv->default_zone);
+ match_data.obj_sexp = query_get_object_sexp (query);
+ if (!match_data.obj_sexp) {
+ query_notify_query_done (query, GNOME_Evolution_Calendar_InvalidQuery);
+ return;
+ }
- if (type & CALOBJ_TYPE_TODO)
- get_instances_in_range (uid_hash, priv->todos, start, end,
- priv->default_zone);
+ g_hash_table_foreach (priv->comp_uid_hash, (GHFunc) match_object_sexp, &match_data);
- if (type & CALOBJ_TYPE_JOURNAL)
- get_instances_in_range (uid_hash, priv->journals, start, end,
- priv->default_zone);
+ /* notify listeners of all objects */
+ if (match_data.obj_list) {
+ query_notify_objects_added (query, (const GList *) match_data.obj_list);
- event_list = NULL;
- g_hash_table_foreach (uid_hash, add_uid_to_list, &event_list);
- g_hash_table_destroy (uid_hash);
+ /* free memory */
+ g_list_foreach (match_data.obj_list, (GFunc) g_free, NULL);
+ g_list_free (match_data.obj_list);
+ }
- return event_list;
+ query_notify_query_done (query, GNOME_Evolution_Calendar_Success);
}
static gboolean
@@ -1155,10 +1011,11 @@ create_user_free_busy (CalBackendFile *cbfile, const char *address, const char *
time_t start, time_t end)
{
CalBackendFilePrivate *priv;
- GList *uids;
GList *l;
icalcomponent *vfb;
icaltimezone *utc_zone;
+ CalBackendObjectSExp *obj_sexp;
+ char *query;
priv = cbfile->priv;
@@ -1181,20 +1038,18 @@ create_user_free_busy (CalBackendFile *cbfile, const char *address, const char *
icalcomponent_set_dtend (vfb, icaltime_from_timet_with_zone (end, FALSE, utc_zone));
/* add all objects in the given interval */
+ query = g_strdup_printf ("occur-in-time-range? %lu %lu", start, end);
+ obj_sexp = cal_backend_object_sexp_new (query);
+ g_free (query);
- uids = cal_backend_get_objects_in_range (CAL_BACKEND (cbfile),
- CALOBJ_TYPE_ANY, start, end);
- for (l = uids; l != NULL; l = l->next) {
- CalComponent *comp;
+ if (!obj_sexp)
+ return vfb;
+
+ for (l = priv->comp; l; l = l->next) {
+ CalComponent *comp = l->data;
icalcomponent *icalcomp, *vcalendar_comp;
icalproperty *prop;
- char *uid = (char *) l->data;
-
- /* get the component from our internal list */
- comp = lookup_component (cbfile, uid);
- if (!comp)
- continue;
-
+
icalcomp = cal_component_get_icalcomponent (comp);
if (!icalcomp)
continue;
@@ -1208,7 +1063,10 @@ create_user_free_busy (CalBackendFile *cbfile, const char *address, const char *
transp_val == ICAL_TRANSP_TRANSPARENTNOCONFLICT)
continue;
}
-
+
+ if (!cal_backend_object_sexp_match_comp (obj_sexp, l->data, CAL_BACKEND (cbfile)))
+ continue;
+
vcalendar_comp = icalcomponent_get_parent (icalcomp);
cal_recur_generate_instances (comp, start, end,
free_busy_instance,
@@ -1216,37 +1074,37 @@ create_user_free_busy (CalBackendFile *cbfile, const char *address, const char *
resolve_tzid,
vcalendar_comp,
priv->default_zone);
-
}
- cal_obj_uid_list_free (uids);
return vfb;
}
/* Get_free_busy handler for the file backend */
-static GList *
-cal_backend_file_get_free_busy (CalBackend *backend, GList *users, time_t start, time_t end)
+static CalBackendSyncStatus
+cal_backend_file_get_free_busy (CalBackendSync *backend, Cal *cal, GList *users,
+ time_t start, time_t end, GList **freebusy)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
gchar *address, *name;
icalcomponent *vfb;
char *calobj;
- GList *obj_list = NULL;
GList *l;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
- g_return_val_if_fail (start != -1 && end != -1, NULL);
- g_return_val_if_fail (start <= end, NULL);
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
+ g_return_val_if_fail (start != -1 && end != -1, GNOME_Evolution_Calendar_InvalidRange);
+ g_return_val_if_fail (start <= end, GNOME_Evolution_Calendar_InvalidRange);
+ *freebusy = NULL;
+
if (users == NULL) {
if (cal_backend_mail_account_get_default (priv->config_listener, &address, &name)) {
vfb = create_user_free_busy (cbfile, address, name, start, end);
calobj = icalcomponent_as_ical_string (vfb);
- obj_list = g_list_append (obj_list, g_strdup (calobj));
+ *freebusy = g_list_append (*freebusy, g_strdup (calobj));
icalcomponent_free (vfb);
g_free (address);
g_free (name);
@@ -1257,34 +1115,31 @@ cal_backend_file_get_free_busy (CalBackend *backend, GList *users, time_t start,
if (cal_backend_mail_account_is_valid (priv->config_listener, address, &name)) {
vfb = create_user_free_busy (cbfile, address, name, start, end);
calobj = icalcomponent_as_ical_string (vfb);
- obj_list = g_list_append (obj_list, g_strdup (calobj));
+ *freebusy = g_list_append (*freebusy, g_strdup (calobj));
icalcomponent_free (vfb);
g_free (name);
}
}
}
- return obj_list;
+ return GNOME_Evolution_Calendar_Success;
}
typedef struct
{
- CalBackend *backend;
+ CalBackendFile *backend;
CalObjType type;
- GList *changes;
- GList *change_ids;
+ GList *deletes;
+ EXmlHash *ehash;
} CalBackendFileComputeChangesData;
static void
cal_backend_file_compute_changes_foreach_key (const char *key, gpointer data)
{
CalBackendFileComputeChangesData *be_data = data;
- char *calobj = cal_backend_get_object (be_data->backend, key);
- if (calobj == NULL) {
+ if (!lookup_component (be_data->backend, key)) {
CalComponent *comp;
- GNOME_Evolution_Calendar_CalObjChange *coc;
- char *calobj;
comp = cal_component_new ();
if (be_data->type == GNOME_Evolution_Calendar_TYPE_TODO)
@@ -1293,319 +1148,283 @@ cal_backend_file_compute_changes_foreach_key (const char *key, gpointer data)
cal_component_set_new_vtype (comp, CAL_COMPONENT_EVENT);
cal_component_set_uid (comp, key);
- calobj = cal_component_get_as_string (comp);
-
- coc = GNOME_Evolution_Calendar_CalObjChange__alloc ();
- coc->calobj = CORBA_string_dup (calobj);
- coc->type = GNOME_Evolution_Calendar_DELETED;
- be_data->changes = g_list_prepend (be_data->changes, coc);
- be_data->change_ids = g_list_prepend (be_data->change_ids, g_strdup (key));
+ be_data->deletes = g_list_prepend (be_data->deletes, cal_component_get_as_string (comp));
- g_free (calobj);
- g_object_unref (comp);
+ e_xmlhash_remove (be_data->ehash, key);
}
}
-static GNOME_Evolution_Calendar_CalObjChangeSeq *
-cal_backend_file_compute_changes (CalBackend *backend, CalObjType type, const char *change_id)
+static CalBackendSyncStatus
+cal_backend_file_compute_changes (CalBackendFile *cbfile, CalObjType type, const char *change_id,
+ GList **adds, GList **modifies, GList **deletes)
{
+ CalBackendFilePrivate *priv;
char *filename;
- EDbHash *ehash;
+ EXmlHash *ehash;
CalBackendFileComputeChangesData be_data;
- GNOME_Evolution_Calendar_CalObjChangeSeq *seq;
- GList *uids, *changes = NULL, *change_ids = NULL;
- GList *i, *j;
- int n;
-
- /* Find the changed ids - FIX ME, path should not be hard coded */
- if (type == GNOME_Evolution_Calendar_TYPE_TODO)
- filename = g_strdup_printf ("%s/evolution/local/Tasks/%s.db", g_get_home_dir (), change_id);
- else
- filename = g_strdup_printf ("%s/evolution/local/Calendar/%s.db", g_get_home_dir (), change_id);
- ehash = e_dbhash_new (filename);
+ GList *i;
+
+ priv = cbfile->priv;
+
+ /* FIXME Will this always work? */
+ filename = g_strdup_printf ("%s/%s.db", priv->uri, change_id);
+ ehash = e_xmlhash_new (filename);
g_free (filename);
- uids = cal_backend_get_uids (backend, type);
-
/* Calculate adds and modifies */
- for (i = uids; i != NULL; i = i->next) {
- GNOME_Evolution_Calendar_CalObjChange *coc;
- char *uid = i->data;
- char *calobj = cal_backend_get_object (backend, uid);
+ for (i = priv->comp; i != NULL; i = i->next) {
+ const char *uid;
+ char *calobj;
+
+ cal_component_get_uid (i->data, &uid);
+ calobj = cal_component_get_as_string (i->data);
g_assert (calobj != NULL);
/* check what type of change has occurred, if any */
- switch (e_dbhash_compare (ehash, uid, calobj)) {
- case E_DBHASH_STATUS_SAME:
+ switch (e_xmlhash_compare (ehash, uid, calobj)) {
+ case E_XMLHASH_STATUS_SAME:
break;
- case E_DBHASH_STATUS_NOT_FOUND:
- coc = GNOME_Evolution_Calendar_CalObjChange__alloc ();
- coc->calobj = CORBA_string_dup (calobj);
- coc->type = GNOME_Evolution_Calendar_ADDED;
- changes = g_list_prepend (changes, coc);
- change_ids = g_list_prepend (change_ids, g_strdup (uid));
+ case E_XMLHASH_STATUS_NOT_FOUND:
+ *adds = g_list_prepend (*adds, g_strdup (calobj));
+ e_xmlhash_add (ehash, uid, calobj);
break;
- case E_DBHASH_STATUS_DIFFERENT:
- coc = GNOME_Evolution_Calendar_CalObjChange__alloc ();
- coc->calobj = CORBA_string_dup (calobj);
- coc->type = GNOME_Evolution_Calendar_MODIFIED;
- changes = g_list_prepend (changes, coc);
- change_ids = g_list_prepend (change_ids, g_strdup (uid));
+ case E_XMLHASH_STATUS_DIFFERENT:
+ *modifies = g_list_prepend (*modifies, g_strdup (calobj));
+ e_xmlhash_add (ehash, uid, calobj);
break;
}
+
+ g_free (calobj);
}
/* Calculate deletions */
- be_data.backend = backend;
+ be_data.backend = cbfile;
be_data.type = type;
- be_data.changes = changes;
- be_data.change_ids = change_ids;
- e_dbhash_foreach_key (ehash, (EDbHashFunc)cal_backend_file_compute_changes_foreach_key, &be_data);
- changes = be_data.changes;
- change_ids = be_data.change_ids;
-
- /* Build the sequence and update the hash */
- n = g_list_length (changes);
-
- seq = GNOME_Evolution_Calendar_CalObjChangeSeq__alloc ();
- seq->_length = n;
- seq->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalObjChange_allocbuf (n);
- CORBA_sequence_set_release (seq, TRUE);
-
- for (i = changes, j = change_ids, n = 0; i != NULL; i = i->next, j = j->next, n++) {
- GNOME_Evolution_Calendar_CalObjChange *coc = i->data;
- GNOME_Evolution_Calendar_CalObjChange *seq_coc;
- char *uid = j->data;
-
- /* sequence building */
- seq_coc = &seq->_buffer[n];
- seq_coc->calobj = CORBA_string_dup (coc->calobj);
- seq_coc->type = coc->type;
-
- /* hash updating */
- if (coc->type == GNOME_Evolution_Calendar_ADDED
- || coc->type == GNOME_Evolution_Calendar_MODIFIED) {
- e_dbhash_add (ehash, uid, coc->calobj);
- } else {
- e_dbhash_remove (ehash, uid);
- }
+ be_data.deletes = NULL;
+ be_data.ehash = ehash;
+ e_xmlhash_foreach_key (ehash, (EXmlHashFunc)cal_backend_file_compute_changes_foreach_key, &be_data);
- CORBA_free (coc);
- g_free (uid);
- }
- e_dbhash_write (ehash);
- e_dbhash_destroy (ehash);
+ *deletes = be_data.deletes;
- cal_obj_uid_list_free (uids);
- g_list_free (change_ids);
- g_list_free (changes);
+ e_xmlhash_write (ehash);
+ e_xmlhash_destroy (ehash);
- return seq;
+ return GNOME_Evolution_Calendar_Success;
}
/* Get_changes handler for the file backend */
-static GNOME_Evolution_Calendar_CalObjChangeSeq *
-cal_backend_file_get_changes (CalBackend *backend, CalObjType type, const char *change_id)
+static CalBackendSyncStatus
+cal_backend_file_get_changes (CalBackendSync *backend, Cal *cal, CalObjType type, const char *change_id,
+ GList **adds, GList **modifies, GList **deletes)
{
- g_return_val_if_fail (backend != NULL, NULL);
- g_return_val_if_fail (IS_CAL_BACKEND (backend), NULL);
+ CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
+
+ cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
+
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
+ g_return_val_if_fail (change_id != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
+
+ return cal_backend_file_compute_changes (cbfile, type, change_id, adds, modifies, deletes);
+}
- return cal_backend_file_compute_changes (backend, type, change_id);
+/* Discard_alarm handler for the file backend */
+static CalBackendSyncStatus
+cal_backend_file_discard_alarm (CalBackendSync *backend, Cal *cal, const char *uid, const char *auid)
+{
+ /* we just do nothing with the alarm */
+ return GNOME_Evolution_Calendar_Success;
}
-/* Get_alarms_in_range handler for the file backend */
-static GNOME_Evolution_Calendar_CalComponentAlarmsSeq *
-cal_backend_file_get_alarms_in_range (CalBackend *backend,
- time_t start, time_t end)
+static CalBackendSyncStatus
+cal_backend_file_create_object (CalBackendSync *backend, Cal *cal, const char *calobj, char **uid)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- int n_comp_alarms;
- GSList *comp_alarms;
- GSList *l;
- int i;
- CalAlarmAction omit[] = {-1};
+ icalcomponent *icalcomp;
+ icalcomponent_kind kind;
+ CalComponent *comp;
+ const char *comp_uid;
+ struct icaltimetype current;
- GNOME_Evolution_Calendar_CalComponentAlarmsSeq *seq;
-
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
-
- g_return_val_if_fail (start != -1 && end != -1, NULL);
- g_return_val_if_fail (start <= end, NULL);
-
- /* Per RFC 2445, only VEVENTs and VTODOs can have alarms */
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
+ g_return_val_if_fail (calobj != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
- n_comp_alarms = 0;
- comp_alarms = NULL;
-
- n_comp_alarms += cal_util_generate_alarms_for_list (priv->events, start, end, omit,
- &comp_alarms, resolve_tzid,
- priv->icalcomp,
- priv->default_zone);
- n_comp_alarms += cal_util_generate_alarms_for_list (priv->todos, start, end, omit,
- &comp_alarms, resolve_tzid,
- priv->icalcomp,
- priv->default_zone);
+ icalcomp = icalparser_parse_string ((char *) calobj);
+ if (!icalcomp)
+ return GNOME_Evolution_Calendar_InvalidObject;
- seq = GNOME_Evolution_Calendar_CalComponentAlarmsSeq__alloc ();
- CORBA_sequence_set_release (seq, TRUE);
- seq->_length = n_comp_alarms;
- seq->_buffer = CORBA_sequence_GNOME_Evolution_Calendar_CalComponentAlarms_allocbuf (
- n_comp_alarms);
+ /* FIXME Check kind with the parent */
+ kind = icalcomponent_isa (icalcomp);
+ if (kind != ICAL_VEVENT_COMPONENT && kind != ICAL_VTODO_COMPONENT) {
+ icalcomponent_free (icalcomp);
+ return GNOME_Evolution_Calendar_InvalidObject;
+ }
- for (l = comp_alarms, i = 0; l; l = l->next, i++) {
- CalComponentAlarms *alarms;
- char *comp_str;
+ /* Get the UID */
+ comp_uid = icalcomponent_get_uid (icalcomp);
+
+ /* check the object is not in our cache */
+ if (lookup_component (cbfile, comp_uid)) {
+ icalcomponent_free (icalcomp);
+ return GNOME_Evolution_Calendar_CardIdAlreadyExists;
+ }
- alarms = l->data;
+ /* Create the cal component */
+ comp = cal_component_new ();
+ cal_component_set_icalcomponent (comp, icalcomp);
- comp_str = cal_component_get_as_string (alarms->comp);
- seq->_buffer[i].calobj = CORBA_string_dup (comp_str);
- g_free (comp_str);
+ /* Set the created and last modified times on the component */
+ current = icaltime_from_timet (time (NULL), 0);
+ cal_component_set_created (comp, &current);
+ cal_component_set_last_modified (comp, &current);
- cal_backend_util_fill_alarm_instances_seq (&seq->_buffer[i].alarms, alarms->alarms);
+ /* Add the object */
+ add_component (cbfile, comp, TRUE);
- cal_component_alarms_free (alarms);
- }
+ /* Mark for saving */
+ mark_dirty (cbfile);
- g_slist_free (comp_alarms);
+ /* Return the UID */
+ if (uid)
+ *uid = g_strdup (comp_uid);
- return seq;
+ return GNOME_Evolution_Calendar_Success;
}
-/* Get_alarms_for_object handler for the file backend */
-static GNOME_Evolution_Calendar_CalComponentAlarms *
-cal_backend_file_get_alarms_for_object (CalBackend *backend, const char *uid,
- time_t start, time_t end,
- gboolean *object_found)
+static CalBackendSyncStatus
+cal_backend_file_modify_object (CalBackendSync *backend, Cal *cal, const char *calobj,
+ CalObjModType mod, char **old_object)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- CalComponent *comp;
- char *comp_str;
- GNOME_Evolution_Calendar_CalComponentAlarms *corba_alarms;
- CalComponentAlarms *alarms;
- CalAlarmAction omit[] = {-1};
+ icalcomponent *icalcomp;
+ icalcomponent_kind kind;
+ const char *comp_uid;
+ CalComponent *comp, *old_comp;
+ struct icaltimetype current;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
+
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
+ g_return_val_if_fail (calobj != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+ icalcomp = icalparser_parse_string ((char *) calobj);
+ if (!icalcomp)
+ return GNOME_Evolution_Calendar_InvalidObject;
- g_return_val_if_fail (uid != NULL, NULL);
- g_return_val_if_fail (start != -1 && end != -1, NULL);
- g_return_val_if_fail (start <= end, NULL);
- g_return_val_if_fail (object_found != NULL, NULL);
+ /* FIXME Check kind with the parent */
+ kind = icalcomponent_isa (icalcomp);
+ if (kind != ICAL_VEVENT_COMPONENT && kind != ICAL_VTODO_COMPONENT) {
+ icalcomponent_free (icalcomp);
+ return GNOME_Evolution_Calendar_InvalidObject;
+ }
- comp = lookup_component (cbfile, uid);
- if (!comp) {
- *object_found = FALSE;
- return NULL;
+ /* Get the uid */
+ comp_uid = icalcomponent_get_uid (icalcomp);
+
+ /* Get the object from our cache */
+ if (!(old_comp = lookup_component (cbfile, comp_uid))) {
+ icalcomponent_free (icalcomp);
+ return GNOME_Evolution_Calendar_ObjectNotFound;
}
- *object_found = TRUE;
+ /* Create the cal component */
+ comp = cal_component_new ();
+ cal_component_set_icalcomponent (comp, icalcomp);
+
+ /* Set the last modified time on the component */
+ current = icaltime_from_timet (time (NULL), 0);
+ cal_component_set_last_modified (comp, &current);
+
+ /* FIXME we need to handle mod types here */
- comp_str = cal_component_get_as_string (comp);
- corba_alarms = GNOME_Evolution_Calendar_CalComponentAlarms__alloc ();
+ /* Remove the old version */
+ remove_component (cbfile, old_comp);
- corba_alarms->calobj = CORBA_string_dup (comp_str);
- g_free (comp_str);
+ /* Add the object */
+ add_component (cbfile, comp, TRUE);
- alarms = cal_util_generate_alarms_for_comp (comp, start, end, omit, resolve_tzid, priv->icalcomp, priv->default_zone);
- if (alarms) {
- cal_backend_util_fill_alarm_instances_seq (&corba_alarms->alarms, alarms->alarms);
- cal_component_alarms_free (alarms);
- } else
- cal_backend_util_fill_alarm_instances_seq (&corba_alarms->alarms, NULL);
+ mark_dirty (cbfile);
- return corba_alarms;
-}
+ if (old_object)
+ *old_object = cal_component_get_as_string (comp);
-/* Discard_alarm handler for the file backend */
-static CalBackendResult
-cal_backend_file_discard_alarm (CalBackend *backend, const char *uid, const char *auid)
-{
- /* we just do nothing with the alarm */
- return CAL_BACKEND_RESULT_SUCCESS;
+ return GNOME_Evolution_Calendar_Success;
}
-/* Creates a CalComponent for the given icalcomponent and adds it to our
- cache. Note that the icalcomponent is not added to the toplevel
- icalcomponent here. That needs to be done elsewhere. It returns the uid
- of the added component, or NULL if it failed. */
-static const char*
-cal_backend_file_update_object (CalBackendFile *cbfile,
- icalcomponent *icalcomp)
+/* Remove_object handler for the file backend */
+static CalBackendSyncStatus
+cal_backend_file_remove_object (CalBackendSync *backend, Cal *cal, const char *uid, const char *rid,
+ CalObjModType mod, char **object)
{
- CalComponent *old_comp;
+ CalBackendFile *cbfile;
+ CalBackendFilePrivate *priv;
CalComponent *comp;
- const char *comp_uid;
- struct icaltimetype last_modified;
- /* Create a CalComponent wrapper for the icalcomponent. */
- comp = cal_component_new ();
- if (!cal_component_set_icalcomponent (comp, icalcomp)) {
- g_object_unref (comp);
- return NULL;
- }
+ cbfile = CAL_BACKEND_FILE (backend);
+ priv = cbfile->priv;
- /* Get the UID, and check it isn't empty. */
- cal_component_get_uid (comp, &comp_uid);
- if (!comp_uid || !comp_uid[0]) {
- g_object_unref (comp);
- return NULL;
- }
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_NoSuchCal);
+ g_return_val_if_fail (uid != NULL, GNOME_Evolution_Calendar_ObjectNotFound);
- /* Set the LAST-MODIFIED time on the component */
- last_modified = icaltime_from_timet (time (NULL), 0);
- cal_component_set_last_modified (comp, &last_modified);
-
- /* Remove any old version of the component. */
- old_comp = lookup_component (cbfile, comp_uid);
- if (old_comp)
- remove_component (cbfile, old_comp);
+ /* FIXME we need to handle mod types here */
- /* Now add the component to our local cache, but we pass FALSE as
- the last argument, since the libical component is assumed to have
- been added already. */
- add_component (cbfile, comp, FALSE);
+ comp = lookup_component (cbfile, uid);
+ if (!comp)
+ return GNOME_Evolution_Calendar_ObjectNotFound;
+
+ *object = cal_component_get_as_string (comp);
+ remove_component (cbfile, comp);
+
+ mark_dirty (cbfile);
- return comp_uid;
+ return GNOME_Evolution_Calendar_Success;
}
-static const char*
-cal_backend_file_cancel_object (CalBackendFile *cbfile,
- icalcomponent *icalcomp)
+static gboolean
+cancel_received_object (CalBackendFile *cbfile, icalcomponent *icalcomp)
{
CalComponent *old_comp;
- icalproperty *uid;
- const char *comp_uid;
-
- /* Get the UID, and check it isn't empty. */
- uid = icalcomponent_get_first_property (icalcomp, ICAL_UID_PROPERTY);
- if (!uid)
- return NULL;
- comp_uid = icalproperty_get_uid (uid);
- if (!comp_uid || !comp_uid[0])
- return NULL;
/* Find the old version of the component. */
- old_comp = lookup_component (cbfile, comp_uid);
+ old_comp = lookup_component (cbfile, icalcomponent_get_uid (icalcomp));
if (!old_comp)
- return NULL;
+ return FALSE;
/* And remove it */
remove_component (cbfile, old_comp);
- return comp_uid;
+
+ return TRUE;
+}
+
+typedef struct {
+ GHashTable *zones;
+
+ gboolean found;
+} CalBackendFileTzidData;
+
+static void
+check_tzids (icalparameter *param, void *data)
+{
+ CalBackendFileTzidData *tzdata = data;
+ const char *tzid;
+
+ tzid = icalparameter_get_tzid (param);
+ if (!tzid || g_hash_table_lookup (tzdata->zones, tzid))
+ tzdata->found = FALSE;
}
/* Update_objects handler for the file backend. */
-static CalBackendResult
-cal_backend_file_update_objects (CalBackend *backend, const char *calobj, CalObjModType mod)
+static CalBackendSyncStatus
+cal_backend_file_receive_objects (CalBackendSync *backend, Cal *cal, const char *calobj,
+ GList **created, GList **modified, GList **removed)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
@@ -1613,143 +1432,153 @@ cal_backend_file_update_objects (CalBackend *backend, const char *calobj, CalObj
icalcomponent_kind kind;
icalproperty_method method;
icalcomponent *subcomp;
- CalBackendResult retval = CAL_BACKEND_RESULT_SUCCESS;
- GList *updated_uids = NULL, *removed_uids = NULL, *elem;
+ GList *comps, *l;
+ CalBackendFileTzidData tzdata;
+ CalBackendSyncStatus status = GNOME_Evolution_Calendar_Success;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (priv->icalcomp != NULL, CAL_BACKEND_RESULT_INVALID_OBJECT);
-
- g_return_val_if_fail (calobj != NULL, CAL_BACKEND_RESULT_INVALID_OBJECT);
+ g_return_val_if_fail (priv->icalcomp != NULL, GNOME_Evolution_Calendar_InvalidObject);
+ g_return_val_if_fail (calobj != NULL, GNOME_Evolution_Calendar_InvalidObject);
/* Pull the component from the string and ensure that it is sane */
-
toplevel_comp = icalparser_parse_string ((char *) calobj);
-
if (!toplevel_comp)
- return CAL_BACKEND_RESULT_INVALID_OBJECT;
+ return GNOME_Evolution_Calendar_InvalidObject;
kind = icalcomponent_isa (toplevel_comp);
-
- if (kind == ICAL_VEVENT_COMPONENT
- || kind == ICAL_VTODO_COMPONENT
- || kind == ICAL_VJOURNAL_COMPONENT) {
- /* Create a temporary toplevel component and put the VEVENT
- or VTODO in it, to simplify the code below. */
+ if (kind != ICAL_VCALENDAR_COMPONENT) {
+ /* If its not a VCALENDAR, make it one to simplify below */
icalcomp = toplevel_comp;
toplevel_comp = cal_util_new_top_level ();
- icalcomponent_add_component (toplevel_comp, icalcomp);
- } else if (kind != ICAL_VCALENDAR_COMPONENT) {
- /* We don't support this type of component */
- icalcomponent_free (toplevel_comp);
- return CAL_BACKEND_RESULT_INVALID_OBJECT;
+ icalcomponent_add_component (toplevel_comp, icalcomp);
}
method = icalcomponent_get_method (toplevel_comp);
- /* Step throught the VEVENT/VTODOs being added, create CalComponents
- for them, and add them to our cache. */
- subcomp = icalcomponent_get_first_component (toplevel_comp,
- ICAL_ANY_COMPONENT);
+ *created = *modified = *removed = NULL;
+
+ /* Build a list of timezones so we can make sure all the objects have valid info */
+ tzdata.zones = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ subcomp = icalcomponent_get_first_component (toplevel_comp, ICAL_VTIMEZONE_COMPONENT);
+ while (subcomp) {
+ icaltimezone *zone;
+
+ zone = icaltimezone_new ();
+ if (icaltimezone_set_component (zone, subcomp))
+ g_hash_table_insert (tzdata.zones, g_strdup (icaltimezone_get_tzid (zone)), NULL);
+
+ subcomp = icalcomponent_get_next_component (toplevel_comp, ICAL_VTIMEZONE_COMPONENT);
+ }
+
+ /* First we make sure all the components are usuable */
+ comps = NULL;
+ subcomp = icalcomponent_get_first_component (toplevel_comp, ICAL_ANY_COMPONENT);
while (subcomp) {
/* We ignore anything except VEVENT, VTODO and VJOURNAL
components. */
icalcomponent_kind child_kind = icalcomponent_isa (subcomp);
- if (child_kind == ICAL_VEVENT_COMPONENT
- || child_kind == ICAL_VTODO_COMPONENT
- || child_kind == ICAL_VJOURNAL_COMPONENT) {
- const char *comp_uid;
-
- if (method == ICAL_METHOD_CANCEL) {
- comp_uid = cal_backend_file_cancel_object (cbfile, subcomp);
- if (comp_uid) {
- removed_uids = g_list_prepend (removed_uids,
- g_strdup (comp_uid));
- } else
- retval = CAL_BACKEND_RESULT_NOT_FOUND;
- } else {
- comp_uid = cal_backend_file_update_object (cbfile, subcomp);
- if (comp_uid) {
- updated_uids = g_list_prepend (updated_uids,
- g_strdup (comp_uid));
- } else
- retval = CAL_BACKEND_RESULT_INVALID_OBJECT;
+
+ switch (child_kind) {
+ case ICAL_VEVENT_COMPONENT:
+ case ICAL_VTODO_COMPONENT:
+ case ICAL_VJOURNAL_COMPONENT:
+ tzdata.found = TRUE;
+ icalcomponent_foreach_tzid (subcomp, check_tzids, &tzdata);
+
+ if (!tzdata.found) {
+ status = GNOME_Evolution_Calendar_InvalidObject;
+ goto error;
}
+
+ if (!icalcomponent_get_uid (subcomp)) {
+ status = GNOME_Evolution_Calendar_InvalidObject;
+ goto error;
+ }
+
+ comps = g_list_prepend (comps, subcomp);
+ break;
+ default:
+ /* Ignore it */
+ break;
}
- subcomp = icalcomponent_get_next_component (toplevel_comp,
- ICAL_ANY_COMPONENT);
+
+ subcomp = icalcomponent_get_next_component (toplevel_comp, ICAL_ANY_COMPONENT);
}
+ /* Now we manipulate the components we care about */
+ for (l = comps; l; l = l->next) {
+ subcomp = l->data;
+
+ switch (method) {
+ case ICAL_METHOD_PUBLISH:
+ case ICAL_METHOD_REQUEST:
+ /* FIXME Need to see the new create/modify stuff before we set this up */
+ break;
+ case ICAL_METHOD_REPLY:
+ /* FIXME Update the status of the user, if we are the organizer */
+ break;
+ case ICAL_METHOD_ADD:
+ /* FIXME This should be doable once all the recurid stuff is done */
+ break;
+ case ICAL_METHOD_COUNTER:
+ status = GNOME_Evolution_Calendar_UnsupportedMethod;
+ goto error;
+ break;
+ case ICAL_METHOD_DECLINECOUNTER:
+ status = GNOME_Evolution_Calendar_UnsupportedMethod;
+ goto error;
+ break;
+ case ICAL_METHOD_CANCEL:
+ /* FIXME Do we need to remove the subcomp so it isn't merged? */
+ if (cancel_received_object (cbfile, subcomp))
+ *removed = g_list_prepend (*removed, g_strdup (icalcomponent_get_uid (subcomp)));
+ break;
+ default:
+ status = GNOME_Evolution_Calendar_UnsupportedMethod;
+ goto error;
+ }
+ }
+ g_list_free (comps);
+
/* Merge the iCalendar components with our existing VCALENDAR,
resolving any conflicting TZIDs. */
icalcomponent_merge_component (priv->icalcomp, toplevel_comp);
mark_dirty (cbfile);
- /* Now emit notification signals for all of the added components.
- We do this after adding them all to make sure the calendar is in a
- stable state before emitting signals. */
- for (elem = updated_uids; elem; elem = elem->next) {
- char *comp_uid = elem->data;
- cal_backend_notify_update (backend, comp_uid);
- g_free (comp_uid);
- }
- g_list_free (updated_uids);
-
- for (elem = removed_uids; elem; elem = elem->next) {
- char *comp_uid = elem->data;
- cal_backend_notify_remove (backend, comp_uid);
- g_free (comp_uid);
- }
- g_list_free (removed_uids);
-
- return retval;
+ error:
+ g_hash_table_destroy (tzdata.zones);
+
+ return status;
}
+static CalBackendSyncStatus
+cal_backend_file_send_objects (CalBackendSync *backend, Cal *cal, const char *calobj)
+{
+ /* FIXME Put in a util routine to send stuff via email */
+
+ return GNOME_Evolution_Calendar_Success;
+}
-/* Remove_object handler for the file backend */
-static CalBackendResult
-cal_backend_file_remove_object (CalBackend *backend, const char *uid, CalObjModType mod)
+static icaltimezone *
+cal_backend_file_internal_get_default_timezone (CalBackend *backend)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- CalComponent *comp;
cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
- g_return_val_if_fail (priv->icalcomp != NULL, CAL_BACKEND_RESULT_INVALID_OBJECT);
-
- g_return_val_if_fail (uid != NULL, CAL_BACKEND_RESULT_NOT_FOUND);
-
- comp = lookup_component (cbfile, uid);
- if (!comp)
- return CAL_BACKEND_RESULT_NOT_FOUND;
-
- remove_component (cbfile, comp);
-
- mark_dirty (cbfile);
-
- cal_backend_notify_remove (backend, uid);
-
- return CAL_BACKEND_RESULT_SUCCESS;
-}
-
-static CalBackendSendResult
-cal_backend_file_send_object (CalBackend *backend, const char *calobj, char **new_calobj,
- GNOME_Evolution_Calendar_UserList **user_list, char error_msg[256])
-{
- *new_calobj = g_strdup (calobj);
-
- *user_list = GNOME_Evolution_Calendar_UserList__alloc ();
- (*user_list)->_length = 0;
+ g_return_val_if_fail (priv->icalcomp != NULL, NULL);
- return CAL_BACKEND_SEND_SUCCESS;
+ return priv->default_zone;
}
-static icaltimezone*
-cal_backend_file_get_timezone (CalBackend *backend, const char *tzid)
+static icaltimezone *
+cal_backend_file_internal_get_timezone (CalBackend *backend, const char *tzid)
{
CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
@@ -1771,43 +1600,134 @@ cal_backend_file_get_timezone (CalBackend *backend, const char *tzid)
return zone;
}
-
-static icaltimezone*
-cal_backend_file_get_default_timezone (CalBackend *backend)
+/* Object initialization function for the file backend */
+static void
+cal_backend_file_init (CalBackendFile *cbfile, CalBackendFileClass *class)
{
- CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- cbfile = CAL_BACKEND_FILE (backend);
- priv = cbfile->priv;
+ priv = g_new0 (CalBackendFilePrivate, 1);
+ cbfile->priv = priv;
- g_return_val_if_fail (priv->icalcomp != NULL, NULL);
+ priv->uri = NULL;
+ priv->file_name = g_strdup ("calendar.ics");
+ priv->icalcomp = NULL;
+ priv->comp_uid_hash = NULL;
+ priv->comp = NULL;
- return priv->default_zone;
+ /* The timezone defaults to UTC. */
+ priv->default_zone = icaltimezone_get_utc_timezone ();
+
+ priv->config_listener = e_config_listener_new ();
}
+/* Class initialization function for the file backend */
+static void
+cal_backend_file_class_init (CalBackendFileClass *class)
+{
+ GObjectClass *object_class;
+ CalBackendClass *backend_class;
+ CalBackendSyncClass *sync_class;
-static gboolean
-cal_backend_file_set_default_timezone (CalBackend *backend,
- const char *tzid)
+ object_class = (GObjectClass *) class;
+ backend_class = (CalBackendClass *) class;
+ sync_class = (CalBackendSyncClass *) class;
+
+ parent_class = (CalBackendSyncClass *) g_type_class_peek_parent (class);
+
+ object_class->dispose = cal_backend_file_dispose;
+ object_class->finalize = cal_backend_file_finalize;
+
+ sync_class->is_read_only_sync = cal_backend_file_is_read_only;
+ sync_class->get_cal_address_sync = cal_backend_file_get_cal_address;
+ sync_class->get_alarm_email_address_sync = cal_backend_file_get_alarm_email_address;
+ sync_class->get_ldap_attribute_sync = cal_backend_file_get_ldap_attribute;
+ sync_class->get_static_capabilities_sync = cal_backend_file_get_static_capabilities;
+ sync_class->open_sync = cal_backend_file_open;
+ sync_class->remove_sync = cal_backend_file_remove;
+ sync_class->create_object_sync = cal_backend_file_create_object;
+ sync_class->modify_object_sync = cal_backend_file_modify_object;
+ sync_class->remove_object_sync = cal_backend_file_remove_object;
+ sync_class->discard_alarm_sync = cal_backend_file_discard_alarm;
+ sync_class->receive_objects_sync = cal_backend_file_receive_objects;
+ sync_class->send_objects_sync = cal_backend_file_send_objects;
+ sync_class->get_default_object_sync = cal_backend_file_get_default_object;
+ sync_class->get_object_sync = cal_backend_file_get_object;
+ sync_class->get_object_list_sync = cal_backend_file_get_object_list;
+ sync_class->get_timezone_sync = cal_backend_file_get_timezone;
+ sync_class->add_timezone_sync = cal_backend_file_add_timezone;
+ sync_class->set_default_timezone_sync = cal_backend_file_set_default_timezone;
+ sync_class->get_freebusy_sync = cal_backend_file_get_free_busy;
+ sync_class->get_changes_sync = cal_backend_file_get_changes;
+
+ backend_class->is_loaded = cal_backend_file_is_loaded;
+ backend_class->start_query = cal_backend_file_start_query;
+ backend_class->get_mode = cal_backend_file_get_mode;
+ backend_class->set_mode = cal_backend_file_set_mode;
+
+ backend_class->internal_get_default_timezone = cal_backend_file_internal_get_default_timezone;
+ backend_class->internal_get_timezone = cal_backend_file_internal_get_timezone;
+}
+
+
+/**
+ * cal_backend_file_get_type:
+ * @void:
+ *
+ * Registers the #CalBackendFile class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the #CalBackendFile class.
+ **/
+GType
+cal_backend_file_get_type (void)
+{
+ static GType cal_backend_file_type = 0;
+
+ if (!cal_backend_file_type) {
+ static GTypeInfo info = {
+ sizeof (CalBackendFileClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) cal_backend_file_class_init,
+ NULL, NULL,
+ sizeof (CalBackendFile),
+ 0,
+ (GInstanceInitFunc) cal_backend_file_init
+ };
+ cal_backend_file_type = g_type_register_static (CAL_TYPE_BACKEND_SYNC,
+ "CalBackendFile", &info, 0);
+ }
+
+ return cal_backend_file_type;
+}
+
+void
+cal_backend_file_set_file_name (CalBackendFile *cbfile, const char *file_name)
{
- CalBackendFile *cbfile;
CalBackendFilePrivate *priv;
- icaltimezone *zone;
+
+ g_return_if_fail (cbfile != NULL);
+ g_return_if_fail (IS_CAL_BACKEND_FILE (cbfile));
+ g_return_if_fail (file_name != NULL);
- cbfile = CAL_BACKEND_FILE (backend);
priv = cbfile->priv;
+
+ if (priv->file_name)
+ g_free (priv->file_name);
+
+ priv->file_name = g_strdup (file_name);
+}
- g_return_val_if_fail (priv->icalcomp != NULL, FALSE);
+const char *
+cal_backend_file_get_file_name (CalBackendFile *cbfile)
+{
+ CalBackendFilePrivate *priv;
- /* Look up the VTIMEZONE in our icalcomponent. */
- zone = icalcomponent_get_timezone (priv->icalcomp, tzid);
- if (!zone)
- return FALSE;
+ g_return_val_if_fail (cbfile != NULL, NULL);
+ g_return_val_if_fail (IS_CAL_BACKEND_FILE (cbfile), NULL);
- /* Set the default timezone to it. */
- priv->default_zone = zone;
+ priv = cbfile->priv;
- return TRUE;
+ return priv->file_name;
}
-