aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/cal-util
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/cal-util')
-rw-r--r--calendar/cal-util/Makefile.am21
-rw-r--r--calendar/cal-util/cal-util.c74
-rw-r--r--calendar/cal-util/cal-util.h60
-rw-r--r--calendar/cal-util/icalendar.c657
-rw-r--r--calendar/cal-util/icalendar.h13
-rw-r--r--calendar/cal-util/timeutil.c501
-rw-r--r--calendar/cal-util/timeutil.h81
7 files changed, 1407 insertions, 0 deletions
diff --git a/calendar/cal-util/Makefile.am b/calendar/cal-util/Makefile.am
new file mode 100644
index 0000000000..c22c0f1948
--- /dev/null
+++ b/calendar/cal-util/Makefile.am
@@ -0,0 +1,21 @@
+
+
+#INCLUDES = \
+# -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
+# -DG_LOG_DOMAIN=\"cal-client\" \
+# -I$(srcdir) -I$(top_srcdir) \
+# -I. \
+# -I.. \
+# -I$(top_builddir) \
+# -I$(includedir) \
+# $(GNOME_INCLUDEDIR)
+
+
+lib_LTLIBRARIES = libcalutil.la
+
+libcalutil_la_SOURCES = \
+ cal-util.c \
+ cal-util.h \
+ timeutil.c \
+ timeutil.h
+
diff --git a/calendar/cal-util/cal-util.c b/calendar/cal-util/cal-util.c
new file mode 100644
index 0000000000..f3054af958
--- /dev/null
+++ b/calendar/cal-util/cal-util.c
@@ -0,0 +1,74 @@
+/* Evolution calendar utilities and types
+ *
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Author: Federico Mena-Quintero <federico@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 <stdlib.h>
+#include "cal-util.h"
+
+
+
+/**
+ * cal_obj_instance_list_free:
+ * @list: List of CalObjInstance structures.
+ *
+ * Frees a list of CalObjInstance structures.
+ **/
+void
+cal_obj_instance_list_free (GList *list)
+{
+ CalObjInstance *i;
+ GList *l;
+
+ for (l = list; l; l = l->next) {
+ i = l->data;
+
+ g_assert (i != NULL);
+ g_assert (i->uid != NULL);
+ g_assert (i->calobj != NULL);
+
+ g_free (i->uid);
+ g_free (i->calobj);
+ g_free (i);
+ }
+
+ g_list_free (list);
+}
+
+/**
+ * cal_obj_uid_list_free:
+ * @list: List of strings with unique identifiers.
+ *
+ * Frees a list of unique identifiers for calendar objects.
+ **/
+void
+cal_obj_uid_list_free (GList *list)
+{
+ GList *l;
+
+ for (l = list; l; l = l->next) {
+ char *uid;
+
+ uid = l->data;
+ g_free (uid);
+ }
+
+ g_list_free (list);
+}
diff --git a/calendar/cal-util/cal-util.h b/calendar/cal-util/cal-util.h
new file mode 100644
index 0000000000..5087eee4d3
--- /dev/null
+++ b/calendar/cal-util/cal-util.h
@@ -0,0 +1,60 @@
+/* Evolution calendar utilities and types
+ *
+ * Copyright (C) 2000 Helix Code, Inc.
+ *
+ * Author: Federico Mena-Quintero <federico@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.
+ */
+
+#ifndef CAL_UTIL_H
+#define CAL_UTIL_H
+
+#include <libgnome/gnome-defs.h>
+#include <time.h>
+#include <glib.h>
+
+BEGIN_GNOME_DECLS
+
+
+
+/* Instance of a calendar object. This can be an actual occurrence, a
+ * recurrence, or an alarm trigger of a `real' calendar object.
+ */
+typedef struct {
+ char *uid; /* Identifier for the object wrapped in calobj */
+ char *calobj; /* String representation of calendar object */
+ time_t start; /* Start time of instance */
+ time_t end; /* End time of instance */
+} CalObjInstance;
+
+void cal_obj_instance_list_free (GList *list);
+
+/* Used for multiple UID queries */
+typedef enum {
+ CALOBJ_TYPE_EVENT = 1 << 0,
+ CALOBJ_TYPE_TODO = 1 << 1,
+ CALOBJ_TYPE_JOURNAL = 1 << 2,
+ CALOBJ_TYPE_OTHER = 1 << 3,
+ CALOBJ_TYPE_ANY = 0x0f
+} CalObjType;
+
+void cal_obj_uid_list_free (GList *list);
+
+
+
+END_GNOME_DECLS
+
+#endif
diff --git a/calendar/cal-util/icalendar.c b/calendar/cal-util/icalendar.c
new file mode 100644
index 0000000000..0a0f39c636
--- /dev/null
+++ b/calendar/cal-util/icalendar.c
@@ -0,0 +1,657 @@
+/*
+ * icalendar server for gnomecal
+ *
+ * This module interfaces between libical and the gnomecal internal
+ * representation
+ *
+ * Copyright (C) 1999 The Free Software Foundation
+ * Authors:
+ * Russell Steinthal (rms39@columbia.edu)
+ *
+ */
+
+#include <config.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include "icalendar.h"
+
+static time_t icaltime_to_timet (struct icaltimetype* i);
+static CalendarAlarm* parse_alarm (icalproperty *prop);
+static iCalPerson* parse_person (icalproperty *prop, gchar *value);
+static iCalRelation* parse_related (icalproperty *prop);
+
+/* Duplicate a string without memory leaks */
+static gchar* copy_str (gchar** store, gchar* src)
+{
+ if (*store)
+ g_free (*store);
+ return (*store = g_strdup (src));
+}
+
+static GList*
+copy_to_list (GList** store, gchar* src)
+{
+ *store = g_list_prepend (*store, g_strdup (src));
+ return *store;
+}
+
+
+iCalObject *
+ical_object_create_from_icalcomponent (icalcomponent* comp)
+{
+ iCalObject *ical = NULL;
+ iCalPerson *person;
+ icalcomponent *subcomp;
+ icalproperty *prop;
+ icalparameter *param;
+ struct icaltimetype ictime;
+ time_t *pt;
+ CalendarAlarm *alarm = NULL;
+ icalcomponent_kind compType;
+ struct icalgeotype geo;
+ struct icalperiodtype period;
+
+ gboolean root = FALSE;
+ gboolean attachment = FALSE;
+
+ char *tmpStr; /* this is a library-owned string */
+
+ ical = g_new0 (iCalObject, 1);
+
+ compType = icalcomponent_isa (comp);
+
+ switch (compType) {
+ case ICAL_XROOT_COMPONENT:
+ root = TRUE;
+ break;
+ case ICAL_XATTACH_COMPONENT:
+ attachment = TRUE;
+ break;
+ case ICAL_VEVENT_COMPONENT:
+ ical->type = ICAL_EVENT;
+ break;
+ case ICAL_VTODO_COMPONENT:
+ ical->type = ICAL_TODO;
+ break;
+ case ICAL_VJOURNAL_COMPONENT:
+ ical->type = ICAL_JOURNAL;
+ break;
+ case ICAL_VCALENDAR_COMPONENT:
+ /* FIXME: what does this mean? */
+ break;
+ case ICAL_VFREEBUSY_COMPONENT:
+ ical->type = ICAL_FBREQUEST;
+ /* NOTE: This is not conclusive- you need to analyze
+ properties to determine whether this is an
+ FBREQUEST or an FBREPLY */
+ break;
+ case ICAL_VTIMEZONE_COMPONENT:
+ ical->type = ICAL_TIMEZONE;
+ break;
+ case ICAL_VALARM_COMPONENT:
+ case ICAL_XAUDIOALARM_COMPONENT:
+ case ICAL_XDISPLAYALARM_COMPONENT:
+ case ICAL_XEMAILALARM_COMPONENT:
+ case ICAL_XPROCEDUREALARM_COMPONENT:
+ /* this should not be reached, since this loop should
+ only be processing first level components */
+ break;
+ case ICAL_XSTANDARD_COMPONENT:
+ /* FIXME: what does this mean? */
+ break;
+ case ICAL_XDAYLIGHT_COMPONENT:
+ /* FIXME: what does this mean? */
+ break;
+ case ICAL_X_COMPONENT:
+ /* FIXME: what does this mean? */
+ break;
+ case ICAL_VSCHEDULE_COMPONENT:
+ /* FIXME: what does this mean? */
+ break;
+ case ICAL_XLICINVALID_COMPONENT:
+ /* FIXME: what does this mean? */
+ break;
+ case ICAL_NO_COMPONENT:
+ case ICAL_ANY_COMPONENT:
+ /* should not occur */
+ break;
+ case ICAL_VQUERY_COMPONENT:
+ case ICAL_VCAR_COMPONENT:
+ case ICAL_VCOMMAND_COMPONENT:
+ /* FIXME: what does this mean? */
+ break;
+ }
+
+ prop = icalcomponent_get_first_property (comp, ICAL_ANY_PROPERTY);
+ while (prop) {
+ switch (icalproperty_isa (prop)) {
+ case ICAL_CALSCALE_PROPERTY:
+ if (g_strcasecmp (icalproperty_get_calscale (prop),
+ "GREGORIAN"))
+ g_warning ("Unknown calendar format.");
+ break;
+ case ICAL_METHOD_PROPERTY:
+ /* FIXME: implement something here */
+ break;
+ case ICAL_ATTACH_PROPERTY:
+ /* FIXME: not yet implemented */
+ break;
+ case ICAL_CATEGORIES_PROPERTY:
+ copy_to_list (&ical->categories,
+ icalproperty_get_categories (prop));
+ break;
+ case ICAL_CLASS_PROPERTY:
+ copy_str (&ical->class, icalproperty_get_class (prop));
+ break;
+ case ICAL_COMMENT_PROPERTY:
+ /*tmpStr = icalproperty_get_comment (prop);*/
+ tmpStr = g_strconcat (icalproperty_get_comment (prop),
+ ical->comment,
+ NULL);
+ if (ical->comment)
+ g_free (ical->comment);
+ ical->comment = tmpStr;
+ break;
+ case ICAL_DESCRIPTION_PROPERTY:
+ copy_str (&ical->desc,
+ icalproperty_get_description (prop));
+ break;
+ case ICAL_GEO_PROPERTY:
+ geo = icalproperty_get_geo (prop);
+ ical->geo.latitude = geo.lat;
+ ical->geo.longitude = geo.lon;
+ ical->geo.valid = TRUE;
+ break;
+ case ICAL_LOCATION_PROPERTY:
+ copy_str (&ical->location,
+ icalproperty_get_location (prop));
+ break;
+ case ICAL_PERCENTCOMPLETE_PROPERTY:
+ ical->percent = icalproperty_get_percentcomplete (prop);
+ break;
+ case ICAL_PRIORITY_PROPERTY:
+ ical->priority = icalproperty_get_priority (prop);
+ if (ical->priority < 0 || ical->priority > 9)
+ g_warning ("Priority out-of-range (see RFC2445)");
+ break;
+ case ICAL_RESOURCES_PROPERTY:
+ copy_to_list (&ical->resources,
+ icalproperty_get_resources (prop));
+ break;
+ case ICAL_STATUS_PROPERTY:
+ copy_str (&ical->status,
+ icalproperty_get_status (prop));
+ break;
+ case ICAL_SUMMARY_PROPERTY:
+ copy_str (&ical->summary,
+ icalproperty_get_summary (prop));
+ break;
+ case ICAL_COMPLETED_PROPERTY:
+ ictime = icalproperty_get_completed (prop);
+ ical->completed = icaltime_to_timet (&ictime);
+ break;
+ case ICAL_DTEND_PROPERTY:
+ ictime = icalproperty_get_dtend (prop);
+ ical->dtend = icaltime_to_timet (&ictime);
+ param = icalproperty_get_first_parameter (prop,
+ ICAL_VALUE_PARAMETER);
+ ical->date_only = (icalparameter_get_value (param) ==
+ ICAL_VALUE_DATE);
+ /* FIXME: We should handle timezone specifiers */
+ break;
+ case ICAL_DUE_PROPERTY:
+ ictime = icalproperty_get_due (prop);
+ ical->dtend = icaltime_to_timet (&ictime);
+ param = icalproperty_get_first_parameter (prop,
+ ICAL_VALUE_PARAMETER);
+ ical->date_only = (icalparameter_get_value (param) ==
+ ICAL_VALUE_DATE);
+ /* FIXME: We should handle timezone specifiers */
+ break;
+ case ICAL_DTSTART_PROPERTY:
+ ictime = icalproperty_get_dtstart (prop);
+ ical->dtstart = icaltime_to_timet (&ictime);
+ param = icalproperty_get_first_parameter (prop,
+ ICAL_VALUE_PARAMETER);
+ ical->date_only = (icalparameter_get_value (param) ==
+ ICAL_VALUE_DATE);
+ /* FIXME: We should handle timezone specifiers */
+ break;
+ case ICAL_DURATION_PROPERTY:
+ /* FIXME: I don't see the necessary libical function */
+ break;
+ case ICAL_FREEBUSY_PROPERTY:
+ period = icalproperty_get_freebusy (prop);
+ ical->dtstart = icaltime_to_timet (&(period.start));
+ /* FIXME: period.end is specified as being relative to start, so
+this may not be correct */
+ ical->dtend = icaltime_to_timet (&(period.end));
+ break;
+ case ICAL_TRANSP_PROPERTY:
+ tmpStr = icalproperty_get_transp (prop);
+ /* do not i18n the following string constant! */
+ if (!g_strcasecmp (tmpStr, "TRANSPARENT"))
+ ical->transp = ICAL_TRANSPARENT;
+ else
+ ical->transp = ICAL_OPAQUE;
+ break;
+ case ICAL_TZID_PROPERTY:
+ case ICAL_TZNAME_PROPERTY:
+ case ICAL_TZOFFSETFROM_PROPERTY:
+ case ICAL_TZOFFSETTO_PROPERTY:
+ case ICAL_TZURL_PROPERTY:
+ /* no implementation for now */
+ break;
+ case ICAL_ATTENDEE_PROPERTY:
+ tmpStr = icalproperty_get_attendee (prop);
+ person = parse_person (prop, tmpStr);
+ ical->attendee = g_list_prepend (ical->attendee,
+ person);
+ break;
+ case ICAL_CONTACT_PROPERTY:
+ tmpStr = icalproperty_get_contact (prop);
+ person = parse_person (prop, tmpStr);
+ ical->contact = g_list_prepend (ical->contact, person);
+ break;
+ case ICAL_ORGANIZER_PROPERTY:
+ tmpStr = icalproperty_get_organizer (prop);
+ person = parse_person (prop, tmpStr);
+ if (ical->organizer)
+ g_free (ical->organizer);
+ ical->organizer = person;
+ break;
+ case ICAL_RECURRENCEID_PROPERTY:
+ ictime = icalproperty_get_recurrenceid (prop);
+ ical->recurid = icaltime_to_timet (&ictime);
+ /* FIXME: Range parameter not implemented */
+ break;
+ case ICAL_RELATEDTO_PROPERTY:
+ ical->related = g_list_prepend (ical->related,
+ parse_related (prop));
+ break;
+ case ICAL_URL_PROPERTY:
+ copy_str (&ical->url,
+ icalproperty_get_url (prop));
+ break;
+ case ICAL_UID_PROPERTY:
+ copy_str (&ical->uid,
+ icalproperty_get_uid (prop));
+ break;
+ case ICAL_EXDATE_PROPERTY:
+ /* FIXME: This does not appear to parse
+ multiple exdate values in one property, as
+ allowed by the RFC; needs a libical fix */
+ ictime = icalproperty_get_exdate (prop);
+ pt = g_new0 (time_t, 1);
+ *pt = icaltime_to_timet (&ictime);
+ ical->exdate = g_list_prepend (ical->exdate, pt);
+ break;
+ case ICAL_EXRULE_PROPERTY:
+ case ICAL_RDATE_PROPERTY:
+ case ICAL_RRULE_PROPERTY:
+ /* FIXME: need recursion processing */
+ break;
+ case ICAL_ACTION_PROPERTY:
+ case ICAL_REPEAT_PROPERTY:
+ case ICAL_TRIGGER_PROPERTY:
+ /* should only occur in VALARM's, handled below */
+ g_assert_not_reached();
+ break;
+ case ICAL_CREATED_PROPERTY:
+ ictime = icalproperty_get_created (prop);
+ ical->created = icaltime_to_timet (&ictime);
+ break;
+ case ICAL_DTSTAMP_PROPERTY:
+ ictime = icalproperty_get_dtstamp (prop);
+ ical->dtstamp = icaltime_to_timet (&ictime);
+ break;
+ case ICAL_LASTMODIFIED_PROPERTY:
+ ictime = icalproperty_get_lastmodified (prop);
+ ical->last_mod = icaltime_to_timet (&ictime);
+ break;
+ case ICAL_SEQUENCE_PROPERTY:
+ ical->seq = icalproperty_get_sequence (prop);
+ break;
+ case ICAL_REQUESTSTATUS_PROPERTY:
+ copy_str (&ical->rstatus,
+ icalproperty_get_requeststatus (prop));
+ break;
+ case ICAL_X_PROPERTY:
+ g_warning ("Unsupported X-property: %s",
+ icalproperty_as_ical_string (prop));
+ break;
+ case ICAL_XLICERROR_PROPERTY:
+ g_warning ("Unsupported property: %s",
+ icalproperty_get_xlicerror (prop));
+ break;
+ case ICAL_PRODID_PROPERTY:
+ case ICAL_VERSION_PROPERTY:
+ /* nothing to do for this property */
+ break;
+ default:
+ g_warning ("Unsupported property: %s", icalproperty_as_ical_string
+(prop));
+ break;
+
+ }
+
+ prop = icalcomponent_get_next_property (comp,
+ ICAL_ANY_PROPERTY);
+ }
+
+ /* now parse subcomponents --- should only be VALARM's */
+ subcomp = icalcomponent_get_first_component (comp,
+ ICAL_ANY_COMPONENT);
+ while (subcomp) {
+ compType = icalcomponent_isa (subcomp);
+ switch (compType) {
+ case ICAL_VALARM_COMPONENT:
+ alarm = parse_alarm (subcomp);
+ if (alarm)
+ ical->alarms = g_list_prepend (ical->alarms,
+ alarm);
+ break;
+ default:
+ g_warning ("Only nested VALARM components are supported.");
+ }
+
+ subcomp = icalcomponent_get_next_component (comp,
+ ICAL_ANY_COMPONENT);
+ }
+
+ return ical;
+}
+
+
+static time_t icaltime_to_timet (struct icaltimetype* i)
+{
+ extern long timezone;
+ struct tm t;
+ time_t ret;
+
+ t.tm_year = i->year - 1900;
+ t.tm_mon = i->month - 1;
+ t.tm_mday = i->day;
+ if (!i->is_date) {
+ t.tm_hour = i->hour;
+ t.tm_min = i->minute;
+ t.tm_sec = i->second;
+ } else {
+ t.tm_hour = 0;
+ t.tm_min = 0;
+ t.tm_sec = 0;
+ }
+
+ ret = mktime(&t);
+
+ return ret - (i->is_utc ? timezone : 0);
+}
+
+static iCalPerson*
+parse_person (icalproperty* prop, gchar* value)
+{
+ icalparameter* param;
+ icalparameter_role role;
+ icalparameter_partstat partstat;
+ icalparameter_cutype cutype;
+
+ iCalPerson* ret;
+
+ ret = g_new0 (iCalPerson, 1);
+
+ ret->addr = g_strdup (value);
+
+ param = icalproperty_get_first_parameter (prop,
+ ICAL_CN_PARAMETER);
+ ret->name = g_strdup (icalparameter_get_cn (param));
+
+ param = icalproperty_get_first_parameter (prop,
+ ICAL_ROLE_PARAMETER);
+ if (param) {
+ role = icalparameter_get_role (param);
+ switch (role) {
+ case ICAL_ROLE_CHAIR:
+ ret->role = g_strdup ("CHAIR");
+ break;
+ case ICAL_ROLE_REQPARTICIPANT:
+ ret->role = g_strdup ("REQPARTICIPANT");
+ break;
+ case ICAL_ROLE_OPTPARTICIPANT:
+ ret->role = g_strdup ("OPTPARTICIPANT");
+ break;
+ case ICAL_ROLE_NONPARTICIPANT:
+ ret->role = g_strdup ("NONPARTICIPANT");
+ break;
+ case ICAL_ROLE_XNAME:
+ default:
+ ret->role = g_strdup ("UNKNOWN");
+ break;
+ }
+ } else
+ ret->role = g_strdup ("REQPARTICIPANT");
+
+ param = icalproperty_get_first_parameter (prop, ICAL_PARTSTAT_PARAMETER);
+ if (param) {
+ partstat = icalparameter_get_partstat (param);
+ switch (partstat) {
+ case ICAL_PARTSTAT_NEEDSACTION:
+ ret->partstat = g_strdup ("NEEDSACTION");
+ break;
+ case ICAL_PARTSTAT_ACCEPTED:
+ ret->partstat = g_strdup ("ACCEPTED");
+ break;
+ case ICAL_PARTSTAT_DECLINED:
+ ret->partstat = g_strdup ("DECLINED");
+ break;
+ case ICAL_PARTSTAT_TENTATIVE:
+ ret->partstat = g_strdup ("TENTATIVE");
+ break;
+ case ICAL_PARTSTAT_DELEGATED:
+ ret->partstat = g_strdup ("DELEGATED");
+ break;
+ case ICAL_PARTSTAT_COMPLETED:
+ ret->partstat = g_strdup ("COMPLETED");
+ break;
+ case ICAL_PARTSTAT_INPROCESS:
+ ret->partstat = g_strdup ("INPROCESS");
+ break;
+ case ICAL_PARTSTAT_XNAME:
+ ret->partstat = g_strdup (icalparameter_get_xvalue (param));
+ break;
+ default:
+ ret->partstat = g_strdup ("UNKNOWN");
+ break;
+ }
+ } else
+ ret->partstat = g_strdup ("NEEDSACTION");
+
+ param = icalproperty_get_first_parameter (prop, ICAL_RSVP_PARAMETER);
+ if (param)
+ ret->rsvp = icalparameter_get_rsvp (param);
+ else
+ ret->rsvp = FALSE;
+
+ param = icalproperty_get_first_parameter (prop, ICAL_CUTYPE_PARAMETER
+);
+ if (param) {
+ cutype = icalparameter_get_cutype (param);
+ switch (cutype) {
+ case ICAL_CUTYPE_INDIVIDUAL:
+ ret->cutype = g_strdup ("INDIVIDUAL");
+ break;
+ case ICAL_CUTYPE_GROUP:
+ ret->cutype = g_strdup ("GROUP");
+ break;
+ case ICAL_CUTYPE_RESOURCE:
+ ret->cutype = g_strdup ("RESOURCE");
+ break;
+ case ICAL_CUTYPE_ROOM:
+ ret->cutype = g_strdup ("ROOM");
+ break;
+ case ICAL_CUTYPE_UNKNOWN:
+ case ICAL_CUTYPE_XNAME:
+ default:
+ ret->cutype = g_strdup ("UNKNOWN");
+ break;
+ }
+ } else
+ ret->cutype = g_strdup ("INDIVIDUAL");
+
+ param = icalproperty_get_first_parameter (prop, ICAL_MEMBER_PARAMETER
+);
+ while (param) {
+ copy_to_list (&ret->member, icalparameter_get_member (param));
+ param = icalproperty_get_next_parameter (prop,
+ ICAL_MEMBER_PARAMETER);
+ }
+
+ param = icalproperty_get_first_parameter (prop, ICAL_DELEGATEDTO_PARAMETER);
+ while (param) {
+ copy_to_list (&ret->deleg_to,
+ icalparameter_get_delegatedto (param));
+ param = icalproperty_get_next_parameter (prop,
+ ICAL_DELEGATEDTO_PARAMETER);
+ }
+
+ param = icalproperty_get_first_parameter (prop, ICAL_DELEGATEDFROM_PARAMETER);
+ while (param) {
+ copy_to_list (&ret->deleg_from,
+ icalparameter_get_delegatedfrom (param));
+ param = icalproperty_get_next_parameter (prop,
+ ICAL_DELEGATEDFROM_PARAMETER);
+ }
+
+ param = icalproperty_get_first_parameter (prop, ICAL_SENTBY_PARAMETER
+);
+ copy_str (&ret->sent_by,
+ icalparameter_get_sentby (param));
+
+ param = icalproperty_get_first_parameter (prop, ICAL_DIR_PARAMETER);
+ while (param) {
+ copy_to_list (&ret->deleg_to,
+ icalparameter_get_delegatedto (param));
+ param = icalproperty_get_next_parameter (prop,
+ ICAL_DIR_PARAMETER);
+ }
+
+ return ret;
+}
+
+static iCalRelation*
+parse_related (icalproperty* prop)
+{
+ iCalRelation* rel;
+ icalparameter* param;
+ icalparameter_reltype type;
+
+ rel = g_new0 (iCalRelation, 1);
+ rel->uid = g_strdup (icalproperty_get_relatedto (prop));
+
+ param = icalproperty_get_first_parameter (prop,
+ ICAL_RELTYPE_PARAMETER);
+ if (param) {
+ type = icalparameter_get_reltype (param);
+ switch (type) {
+ case ICAL_RELTYPE_PARENT:
+ rel->reltype = g_strdup ("PARENT");
+ break;
+ case ICAL_RELTYPE_CHILD:
+ rel->reltype = g_strdup ("CHILD");
+ break;
+ case ICAL_RELTYPE_SIBLING:
+ rel->reltype = g_strdup ("SIBLING");
+ break;
+ case ICAL_RELTYPE_XNAME:
+ rel->reltype = g_strdup (icalparameter_get_xvalue (param));
+ break;
+ default:
+ rel->reltype = g_strdup ("UNKNOWN");
+ break;
+ }
+ } else
+ rel->reltype = g_strdup ("PARENT");
+
+ return rel;
+}
+
+#ifdef TEST
+
+int main(int argc, char* argv[])
+{
+ icalcomponent* comp;
+ comp = icalendar_parse_file (argv[1]);
+ printf ("%s\n", icalcomponent_as_ical_string (comp));
+ return 0;
+}
+
+#endif
+
+
+static CalendarAlarm*
+parse_alarm (icalcomponent* comp)
+{
+ CalendarAlarm *alarm;
+ icalproperty *prop;
+ char *tmpStr;
+ struct icaldurationtype dur;
+ struct icalattachtype attach;
+
+ g_return_val_if_fail (comp != NULL, NULL);
+
+ alarm = g_new0 (CalendarAlarm, 1);
+
+ prop = icalcomponent_get_first_property (comp, ICAL_ANY_PROPERTY);
+ while (prop) {
+ switch (icalproperty_isa (prop)) {
+ case ICAL_ACTION_PROPERTY:
+ tmpStr = icalproperty_get_action (prop);
+ if (!g_strcasecmp (tmpStr, "AUDIO"))
+ alarm->type = ALARM_AUDIO;
+ else if (!g_strcasecmp (tmpStr, "DISPLAY"))
+ alarm->type = ALARM_DISPLAY;
+ else if (!g_strcasecmp (tmpStr, "EMAIL"))
+ alarm->type = ALARM_MAIL;
+ else if (!g_strcasecmp (tmpStr, "PROCEDURE"))
+ alarm->type = ALARM_PROGRAM;
+ else
+ g_warning ("Unsupported alarm type!");
+ break;
+ case ICAL_TRIGGER_PROPERTY:
+ /* FIXME: waiting on proper libical support */
+ break;
+ case ICAL_REPEAT_PROPERTY:
+ alarm->snooze_repeat = icalproperty_get_repeat (prop);
+ break;
+ case ICAL_DURATION_PROPERTY:
+ dur = icalproperty_get_duration (prop);
+ alarm->snooze_secs = icaldurationtype_as_timet (dur);
+ break;
+ case ICAL_ATTACH_PROPERTY:
+ attach = icalproperty_get_attach (prop);
+ copy_str (&alarm->attach,
+ icalattachtype_get_url (&attach));
+ break;
+ case ICAL_DESCRIPTION_PROPERTY:
+ copy_str (&alarm->desc,
+ icalproperty_get_description (prop));
+ break;
+ case ICAL_SUMMARY_PROPERTY:
+ copy_str (&alarm->summary,
+ icalproperty_get_summary (prop));
+ break;
+ case ICAL_ATTENDEE_PROPERTY:
+ copy_str (&alarm->attendee,
+ icalproperty_get_attendee (prop));
+ break;
+ default:
+ g_warning ("Unsupported alarm property: %s",
+ icalproperty_as_ical_string (prop));
+ break;
+ }
+
+ prop = icalcomponent_get_next_property (comp,
+ ICAL_ANY_PROPERTY);
+ }
+
+ return alarm;
+}
diff --git a/calendar/cal-util/icalendar.h b/calendar/cal-util/icalendar.h
new file mode 100644
index 0000000000..09bfa06fad
--- /dev/null
+++ b/calendar/cal-util/icalendar.h
@@ -0,0 +1,13 @@
+#ifndef ICALENDAR_H
+#define ICALENDAR_H
+
+#include <ical.h>
+#include "calobj.h"
+
+
+
+iCalObject *ical_object_create_from_icalcomponent (icalcomponent* comp);
+
+
+
+#endif
diff --git a/calendar/cal-util/timeutil.c b/calendar/cal-util/timeutil.c
new file mode 100644
index 0000000000..7ddc0e04d4
--- /dev/null
+++ b/calendar/cal-util/timeutil.c
@@ -0,0 +1,501 @@
+/* Miscellaneous time-related utilities
+ *
+ * Copyright (C) 1998 The Free Software Foundation
+ *
+ * Authors: Federico Mena <federico@nuclecu.unam.mx>
+ * Miguel de Icaza <miguel@nuclecu.unam.mx>
+ */
+
+#include <libgnome/libgnome.h>
+#include <string.h>
+#include "timeutil.h"
+
+#define digit_at(x,y) (x [y] - '0')
+
+time_t
+time_from_isodate (char *str)
+{
+ struct tm my_tm;
+ time_t t;
+
+ if (strlen (str) < 14)
+ return -1;
+
+ my_tm.tm_year = (digit_at (str, 0) * 1000 + digit_at (str, 1) * 100 +
+ digit_at (str, 2) * 10 + digit_at (str, 3)) - 1900;
+
+ my_tm.tm_mon = digit_at (str, 4) * 10 + digit_at (str, 5) - 1;
+ my_tm.tm_mday = digit_at (str, 6) * 10 + digit_at (str, 7);
+ my_tm.tm_hour = digit_at (str, 9) * 10 + digit_at (str, 10);
+ my_tm.tm_min = digit_at (str, 11) * 10 + digit_at (str, 12);
+ my_tm.tm_sec = digit_at (str, 13) * 10 + digit_at (str, 14);
+ my_tm.tm_isdst = -1;
+
+ t = mktime (&my_tm);
+
+ if (str [15] == 'Z')
+#if defined(HAVE_TM_GMTOFF)
+ t -= my_tm.tm_gmtoff
+#elsif defined(HAVE_TIMEZONE)
+ t -= timezone
+#endif
+ ;
+
+ return t;
+}
+
+void
+print_time_t (time_t t)
+{
+ struct tm *tm = localtime (&t);
+
+ printf ("TIEMPO: %d/%d/%d %d:%d:%d\n",
+ tm->tm_mon+1, tm->tm_mday, tm->tm_year,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+
+int
+get_time_t_hour (time_t t)
+{
+ struct tm *tm;
+
+ tm = localtime (&t);
+ return tm->tm_hour;
+}
+
+char *
+isodate_from_time_t (time_t t)
+{
+ struct tm *tm;
+ static char isotime [40];
+
+ tm = localtime (&t);
+ strftime (isotime, sizeof (isotime)-1, "%Y%m%dT%H%M%S", tm);
+ return isotime;
+}
+
+time_t
+time_from_start_duration (time_t start, char *duration)
+{
+ printf ("Not yet implemented\n");
+ return 0;
+}
+
+char *
+format_simple_hour (int hour, int use_am_pm)
+{
+ static char buf[256];
+
+ /* I don't know whether this is the best way to internationalize it.
+ * Does any language use different conventions? - Federico
+ */
+
+ if (use_am_pm)
+ g_snprintf (buf, sizeof(buf), "%d%s",
+ (hour == 0) ? 12 : (hour > 12) ? (hour - 12) : hour,
+ (hour < 12) ? _("am") : _("pm"));
+ else
+ g_snprintf (buf, sizeof(buf), "%02d%s", hour, _("h"));
+
+ return buf;
+
+}
+
+time_t
+time_add_minutes (time_t time, int minutes)
+{
+ struct tm *tm = localtime (&time);
+ time_t new_time;
+
+ tm->tm_min += minutes;
+ if ((new_time = mktime (tm)) == -1){
+ g_warning ("mktime could not handling adding a day with\n");
+ print_time_t (time);
+ return time;
+ }
+ return new_time;
+}
+
+time_t
+time_add_day (time_t time, int days)
+{
+ struct tm *tm = localtime (&time);
+ time_t new_time;
+ int dst_flag = tm->tm_isdst;
+
+ tm->tm_mday += days;
+
+ if ((new_time = mktime (tm)) == -1){
+ g_warning ("mktime could not handling adding a day with\n");
+ print_time_t (time);
+ return time;
+ }
+
+ if (dst_flag > tm->tm_isdst){
+ tm->tm_hour++;
+ new_time += 3600;
+ } else if (dst_flag < tm->tm_isdst){
+ tm->tm_hour--;
+ new_time -= 3600;
+ }
+
+ return new_time;
+}
+
+time_t
+time_add_week (time_t time, int weeks)
+{
+ return time_add_day (time, weeks * 7);
+}
+
+time_t
+time_add_month (time_t time, int months)
+{
+ struct tm *tm = localtime (&time);
+ time_t new_time;
+ int mday;
+
+ mday = tm->tm_mday;
+
+ tm->tm_mon += months;
+ tm->tm_isdst = -1;
+ if ((new_time = mktime (tm)) == -1){
+ g_warning ("mktime could not handling adding a month with\n");
+ print_time_t (time);
+ return time;
+ }
+ tm = localtime (&new_time);
+ if (tm->tm_mday < mday){
+ tm->tm_mon--;
+ tm->tm_mday = time_days_in_month (tm->tm_year+1900, tm->tm_mon);
+ return new_time = mktime (tm);
+ }
+ else
+ return new_time;
+}
+
+time_t
+time_add_year (time_t time, int years)
+{
+ struct tm *tm = localtime (&time);
+ time_t new_time;
+
+ tm->tm_year += years;
+ if ((new_time = mktime (tm)) == -1){
+ g_warning ("mktime could not handling adding a year with\n");
+ print_time_t (time);
+ return time;
+ }
+ return new_time;
+}
+
+time_t
+time_day_hour (time_t t, int hour)
+{
+ struct tm tm;
+
+ tm = *localtime (&t);
+ tm.tm_hour = hour;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+
+ return mktime (&tm);
+}
+
+/* Number of days in a month, for normal and leap years */
+static const int days_in_month[2][12] = {
+ { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+/* Returns whether the specified year is a leap year */
+static int
+is_leap_year (int year)
+{
+ if (year <= 1752)
+ return !(year % 4);
+ else
+ return (!(year % 4) && (year % 100)) || !(year % 400);
+}
+
+int
+time_days_in_month (int year, int month)
+{
+ g_return_val_if_fail (year >= 1900, 0);
+ g_return_val_if_fail ((month >= 0) && (month < 12), 0);
+
+ return days_in_month [is_leap_year (year)][month];
+}
+
+time_t
+time_from_day (int year, int month, int day)
+{
+ struct tm tm;
+
+ memset (&tm, 0, sizeof (tm));
+ tm.tm_year = year - 1900;
+ tm.tm_mon = month;
+ tm.tm_mday = day;
+
+ return mktime (&tm);
+}
+
+time_t
+time_year_begin (time_t t)
+{
+ struct tm tm;
+
+ tm = *localtime (&t);
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_mon = 0;
+ tm.tm_mday = 1;
+ tm.tm_isdst = -1;
+
+ return mktime (&tm);
+}
+
+time_t
+time_year_end (time_t t)
+{
+ struct tm tm;
+
+ tm = *localtime (&t);
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_mon = 0;
+ tm.tm_mday = 1;
+ tm.tm_year++;
+ tm.tm_isdst = -1;
+
+ return mktime (&tm);
+}
+
+time_t
+time_month_begin (time_t t)
+{
+ struct tm tm;
+
+ tm = *localtime (&t);
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_mday = 1;
+ tm.tm_isdst = -1;
+
+ return mktime (&tm);
+}
+
+time_t
+time_month_end (time_t t)
+{
+ struct tm tm;
+
+ tm = *localtime (&t);
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_mday = 1;
+ tm.tm_mon++;
+ tm.tm_isdst = -1;
+
+ return mktime (&tm);
+}
+
+time_t
+time_week_begin (time_t t)
+{
+ struct tm tm;
+
+ /* FIXME: make it take week_starts_on_monday into account */
+
+ tm = *localtime (&t);
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_mday -= tm.tm_wday;
+
+ return mktime (&tm);
+}
+
+time_t
+time_week_end (time_t t)
+{
+ struct tm tm;
+
+ /* FIXME: make it take week_starts_on_monday into account */
+
+ tm = *localtime (&t);
+ tm.tm_hour = 0;
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+ tm.tm_mday += 7 - tm.tm_wday;
+
+ return mktime (&tm);
+}
+
+time_t
+time_day_begin (time_t t)
+{
+ struct tm tm;
+ time_t temp = t - 43200;
+ int dstflag, dstflag2;
+
+ tm = *localtime(&temp); /* one day */
+ dstflag = tm.tm_isdst;
+
+ tm = *localtime (&t);
+ dstflag2 = tm.tm_isdst;
+
+ if (dstflag < dstflag2)
+ tm.tm_hour = 1;
+ else
+ tm.tm_hour = 0;
+
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+
+ temp = mktime(&tm);
+ if (dstflag > dstflag2){
+ temp += 3600;
+ }
+
+ return temp;
+}
+
+time_t
+time_day_end (time_t t)
+{
+ struct tm tm;
+ time_t temp;
+ int dstflag, dstflag2;
+
+ t += 10800;
+ temp = t - 86400;
+
+ tm = *localtime(&temp); /* one day */
+ dstflag = tm.tm_isdst;
+
+ tm = *localtime (&t);
+ dstflag2 = tm.tm_isdst;
+
+ if (dstflag < dstflag2)
+ tm.tm_hour = 23;
+ else {
+ tm.tm_mday++;
+ tm.tm_hour = 0;
+ }
+ tm.tm_min = 0;
+ tm.tm_sec = 0;
+
+ temp = mktime(&tm);
+ if(dstflag > dstflag2) {
+ }
+ return temp;
+}
+
+static char *
+pcat (char *dest, int num, char key)
+{
+ int c;
+
+ c = sprintf (dest, "%d%c", num, key);
+ return dest + c;
+}
+
+/* Converts secs into the ISO difftime representation */
+char *
+isodiff_from_secs (int secs)
+{
+ static char buffer [60], *p;
+ int years, months, weeks, days, hours, minutes;
+
+ years = months = weeks = days = hours = minutes = 0;
+
+ years = secs / (365 * 86400);
+ secs %= (365 * 86400);
+ months = secs / (30 * 86400);
+ secs %= (30 * 86400);
+ weeks = secs / (7 * 86400);
+ secs %= (7 * 86400);
+ days = secs / 86400;
+ secs %= 86400;
+ hours = secs / 3600;
+ secs %= 3600;
+ minutes = secs / 60;
+ secs %= 60;
+
+ strcpy (buffer, "P");
+ p = buffer + 1;
+ if (years)
+ p = pcat (p, years, 'Y');
+ if (months)
+ p = pcat (p, months, 'M');
+ if (weeks)
+ p = pcat (p, weeks, 'W');
+ if (days)
+ p = pcat (p, days, 'D');
+ if (hours || minutes || secs){
+ *p++ = 'T';
+ if (hours)
+ p = pcat (p, hours, 'H');
+ if (minutes)
+ p = pcat (p, minutes, 'M');
+ if (secs)
+ p = pcat (p, secs, 'S');
+ }
+
+ return buffer;
+}
+
+int
+isodiff_to_secs (char *str)
+{
+ int value, time;
+ int years, months, weeks, days, hours, minutes, seconds;
+
+ value = years = months = weeks = days = hours = minutes = time = seconds = 0;
+ if (*str != 'P')
+ return 0;
+
+ str++;
+ while (*str){
+ switch (*str){
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ value = value * 10 + (*str - '0');
+ break;
+ case 'Y':
+ years = value; value = 0;
+ break;
+ case 'M':
+ if (time)
+ minutes = value;
+ else
+ months = value;
+ value = 0;
+ break;
+ case 'W':
+ weeks = value; value = 0;
+ break;
+ case 'D':
+ days = value; value = 0;
+ break;
+ case 'T':
+ value = 0; time = 1;
+ break;
+ case 'H':
+ hours = value; value = 0;
+ break;
+ case 'S':
+ seconds = value; value = 0;
+ break;
+ }
+ str++;
+ }
+ return seconds + (minutes * 60) + (hours * 3600) +
+ (days * 86400) + (weeks * 7 * 86400) +
+ (months * 30 * 86400) + (years * 365 * 86400);
+}
diff --git a/calendar/cal-util/timeutil.h b/calendar/cal-util/timeutil.h
new file mode 100644
index 0000000000..407213d7f8
--- /dev/null
+++ b/calendar/cal-util/timeutil.h
@@ -0,0 +1,81 @@
+/* Miscellaneous time-related utilities
+ *
+ * Copyright (C) 1998 The Free Software Foundation
+ *
+ * Authors: Federico Mena <federico@nuclecu.unam.mx>
+ * Miguel de Icaza <miguel@nuclecu.unam.mx>
+ */
+
+#ifndef TIMEUTIL_H
+#define TIMEUTIL_H
+
+
+#include <time.h>
+
+
+time_t time_from_isodate (char *str);
+time_t time_from_start_duration (time_t start, char *duration);
+char *isodate_from_time_t (time_t t);
+int get_time_t_hour (time_t t);
+int isodiff_to_secs (char *str);
+char *isodiff_from_secs (int secs);
+
+time_t time_add_minutes (time_t time, int minutes);
+time_t time_add_day (time_t time, int days);
+time_t time_add_week (time_t time, int weeks);
+time_t time_add_month (time_t time, int months);
+time_t time_add_year (time_t time, int years);
+
+
+/* Returns pointer to a statically-allocated buffer with a string of the form
+ * 3am, 4am, 12pm, 08h, 17h, etc.
+ * The string is internationalized, hopefully correctly.
+ */
+char *format_simple_hour (int hour, int use_am_pm);
+
+/* Returns the number of days in the specified month. Years are full years (starting from year 1).
+ * Months are in [0, 11].
+ */
+int time_days_in_month (int year, int month);
+
+/* Converts the specified date to a time_t at the start of the specified day. Years are full years
+ * (starting from year 1). Months are in [0, 11]. Days are 1-based.
+ */
+time_t time_from_day (int year, int month, int day);
+
+time_t time_day_hour (time_t t, int hour);
+
+/* For the functions below, time ranges are considered to contain the start time, but not the end
+ * time.
+ */
+
+/* These two functions take a time value and return the beginning or end of the corresponding year,
+ * respectively.
+ */
+time_t time_year_begin (time_t t);
+time_t time_year_end (time_t t);
+
+/* These two functions take a time value and return the beginning or end of the corresponding month,
+ * respectively.
+ */
+time_t time_month_begin (time_t t);
+time_t time_month_end (time_t t);
+
+/* These functions take a time value and return the beginning or end of the corresponding week,
+ * respectively. This takes into account the global week_starts_on_monday flag.
+ */
+time_t time_week_begin (time_t t);
+time_t time_week_end (time_t t);
+
+/* These two functions take a time value and return the beginning or end of the corresponding day,
+ * respectively.
+ */
+time_t time_day_begin (time_t t);
+time_t time_day_end (time_t t);
+
+
+time_t parse_date (char *str);
+void print_time_t (time_t t);
+
+
+#endif