From c6c65136bb37bd87e9d50735e1543bd296ee513d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 4 Mar 2000 03:58:38 +0000 Subject: new file -- things shared between the client and server go in this * cal-util/Makefile.am: new file -- things shared between the client and server go in this directory * calobj.c calobj.h icalendar.c icalendar.h timeutil.c timeutil.h cal-util.c cal-util.h where moved backend stuff went into pcs. shared stuff went into cal-util. svn path=/trunk/; revision=2032 --- calendar/cal-util/Makefile.am | 21 ++ calendar/cal-util/cal-util.c | 74 +++++ calendar/cal-util/cal-util.h | 60 ++++ calendar/cal-util/icalendar.c | 657 ++++++++++++++++++++++++++++++++++++++++++ calendar/cal-util/icalendar.h | 13 + calendar/cal-util/timeutil.c | 501 ++++++++++++++++++++++++++++++++ calendar/cal-util/timeutil.h | 81 ++++++ 7 files changed, 1407 insertions(+) create mode 100644 calendar/cal-util/Makefile.am create mode 100644 calendar/cal-util/cal-util.c create mode 100644 calendar/cal-util/cal-util.h create mode 100644 calendar/cal-util/icalendar.c create mode 100644 calendar/cal-util/icalendar.h create mode 100644 calendar/cal-util/timeutil.c create mode 100644 calendar/cal-util/timeutil.h (limited to 'calendar/cal-util') 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 + * + * 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 +#include +#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 + * + * 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 +#include +#include + +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 +#include +#include +#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 +#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 + * Miguel de Icaza + */ + +#include +#include +#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 + * Miguel de Icaza + */ + +#ifndef TIMEUTIL_H +#define TIMEUTIL_H + + +#include + + +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 -- cgit v1.2.3