summaryrefslogtreecommitdiffstats
path: root/libkcal/libical/src/libical/icalcomponent.c
diff options
context:
space:
mode:
Diffstat (limited to 'libkcal/libical/src/libical/icalcomponent.c')
-rw-r--r--libkcal/libical/src/libical/icalcomponent.c2598
1 files changed, 0 insertions, 2598 deletions
diff --git a/libkcal/libical/src/libical/icalcomponent.c b/libkcal/libical/src/libical/icalcomponent.c
deleted file mode 100644
index bab0e72a..00000000
--- a/libkcal/libical/src/libical/icalcomponent.c
+++ /dev/null
@@ -1,2598 +0,0 @@
-/*======================================================================
- FILE: icalcomponent.c
- CREATOR: eric 28 April 1999
-
-
- (C) COPYRIGHT 2000, Eric Busboom <eric@softwarestudio.org>
- http://www.softwarestudio.org
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of either:
-
- The LGPL as published by the Free Software Foundation, version
- 2.1, available at: http://www.fsf.org/copyleft/lesser.html
-
- Or:
-
- The Mozilla Public License Version 1.0. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- The original code is icalcomponent.c
-
-======================================================================*/
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "icalcomponent.h"
-#include "pvl.h" /* "Pointer-to-void list" */
-#include "icalerror.h"
-#include "icalmemory.h"
-#include "icalenums.h"
-#include "icaltime.h"
-#include "icalarray.h"
-#include "icaltimezone.h"
-#include "icalduration.h"
-#include "icalperiod.h"
-#include "icalparser.h"
-#include "icalrestriction.h"
-
-#include <stdlib.h> /* for malloc */
-#include <stdarg.h> /* for va_list, etc */
-#include <errno.h>
-#include <assert.h>
-#include <stdio.h> /* for fprintf */
-#include <string.h> /* for strdup */
-#include <limits.h> /* for INT_MAX */
-
-struct icalcomponent_impl
-{
- char id[5];
- icalcomponent_kind kind;
- char* x_name;
- pvl_list properties;
- pvl_elem property_iterator;
- pvl_list components;
- pvl_elem component_iterator;
- icalcomponent* parent;
-
- /** An array of icaltimezone structs. We use this so we can do fast
- lookup of timezones using binary searches. timezones_sorted is
- set to 0 whenever we add a timezone, so we remember to sort the
- array before doing a binary search. */
- icalarray* timezones;
- int timezones_sorted;
-};
-
-/* icalproperty functions that only components get to use */
-void icalproperty_set_parent(icalproperty* property,
- icalcomponent* component);
-icalcomponent* icalproperty_get_parent(icalproperty* property);
-void icalcomponent_add_children(icalcomponent *impl,va_list args);
-static icalcomponent* icalcomponent_new_impl (icalcomponent_kind kind);
-
-static void icalcomponent_merge_vtimezone (icalcomponent *comp,
- icalcomponent *vtimezone,
- icalarray *tzids_to_rename);
-static void icalcomponent_handle_conflicting_vtimezones (icalcomponent *comp,
- icalcomponent *vtimezone,
- icalproperty *tzid_prop,
- const char *tzid,
- icalarray *tzids_to_rename);
-static unsigned int icalcomponent_get_tzid_prefix_len (const char *tzid);
-static void icalcomponent_rename_tzids(icalcomponent* comp,
- icalarray* rename_table);
-static void icalcomponent_rename_tzids_callback(icalparameter *param,
- void *data);
-static int icalcomponent_compare_vtimezones (icalcomponent *vtimezone1,
- icalcomponent *vtimezone2);
-static int icalcomponent_compare_timezone_fn (const void *elem1,
- const void *elem2);
-
-
-void icalcomponent_add_children(icalcomponent *impl, va_list args)
-{
- void* vp;
-
- while((vp = va_arg(args, void*)) != 0) {
-
- assert (icalcomponent_isa_component(vp) != 0 ||
- icalproperty_isa_property(vp) != 0 ) ;
-
- if (icalcomponent_isa_component(vp) != 0 ){
- icalcomponent_add_component(impl, (icalcomponent*)vp);
-
- } else if (icalproperty_isa_property(vp) != 0 ){
- icalcomponent_add_property(impl, (icalproperty*)vp);
- }
- }
-}
-
-static icalcomponent*
-icalcomponent_new_impl (icalcomponent_kind kind)
-{
- icalcomponent* comp;
-
- if (!icalcomponent_kind_is_valid(kind))
- return NULL;
-
- if ( ( comp = (icalcomponent*) malloc(sizeof(icalcomponent))) == 0) {
- icalerror_set_errno(ICAL_NEWFAILED_ERROR);
- return 0;
- }
-
- strcpy(comp->id,"comp");
-
- comp->kind = kind;
- comp->properties = pvl_newlist();
- comp->property_iterator = 0;
- comp->components = pvl_newlist();
- comp->component_iterator = 0;
- comp->x_name = 0;
- comp->parent = 0;
- comp->timezones = NULL;
- comp->timezones_sorted = 1;
-
- return comp;
-}
-
-/** @brief Constructor
- */
-icalcomponent*
-icalcomponent_new (icalcomponent_kind kind)
-{
- return icalcomponent_new_impl(kind);
-}
-
-/** @brief Constructor
- */
-icalcomponent*
-icalcomponent_vanew (icalcomponent_kind kind, ...)
-{
- va_list args;
-
- icalcomponent *impl = icalcomponent_new_impl(kind);
-
- if (impl == 0){
- return 0;
- }
-
- va_start(args,kind);
- icalcomponent_add_children(impl, args);
- va_end(args);
-
- return impl;
-}
-
-/** @brief Constructor
- */
-icalcomponent* icalcomponent_new_from_string(char* str)
-{
- return icalparser_parse_string(str);
-}
-
-/** @brief Constructor
- */
-icalcomponent* icalcomponent_new_clone(icalcomponent* old)
-{
- icalcomponent *new;
- icalproperty *p;
- icalcomponent *c;
- pvl_elem itr;
-
- icalerror_check_arg_rz( (old!=0), "component");
-
- new = icalcomponent_new_impl(old->kind);
-
- if (new == 0){
- return 0;
- }
-
-
- for( itr = pvl_head(old->properties);
- itr != 0;
- itr = pvl_next(itr))
- {
- p = (icalproperty*)pvl_data(itr);
- icalcomponent_add_property(new,icalproperty_new_clone(p));
- }
-
-
- for( itr = pvl_head(old->components);
- itr != 0;
- itr = pvl_next(itr))
- {
- c = (icalcomponent*)pvl_data(itr);
- icalcomponent_add_component(new,icalcomponent_new_clone(c));
- }
-
- return new;
-
-}
-
-/*** @brief Destructor
- */
-void
-icalcomponent_free (icalcomponent* c)
-{
- icalproperty* prop;
- icalcomponent* comp;
-
- icalerror_check_arg_rv( (c!=0), "component");
-
-#ifdef ICAL_FREE_ON_LIST_IS_ERROR
- icalerror_assert( (c->parent ==0),"Tried to free a component that is still attached to a parent component");
-#else
- if(c->parent != 0){
- return;
- }
-#endif
-
- if(c != 0 ){
-
- if ( c->properties != 0 )
- {
- while( (prop=pvl_pop(c->properties)) != 0){
- assert(prop != 0);
- icalproperty_set_parent(prop,0);
- icalproperty_free(prop);
- }
- pvl_free(c->properties);
- }
-
-
- while( (comp=pvl_data(pvl_head(c->components))) != 0){
- assert(comp!=0);
- icalcomponent_remove_component(c,comp);
- icalcomponent_free(comp);
- }
-
- pvl_free(c->components);
-
- if (c->x_name != 0) {
- free(c->x_name);
- }
-
- if (c->timezones)
- icaltimezone_array_free (c->timezones);
-
- c->kind = ICAL_NO_COMPONENT;
- c->properties = 0;
- c->property_iterator = 0;
- c->components = 0;
- c->component_iterator = 0;
- c->x_name = 0;
- c->id[0] = 'X';
- c->timezones = NULL;
-
- free(c);
- }
-}
-
-char*
-icalcomponent_as_ical_string (icalcomponent* impl)
-{
- char* buf, *out_buf;
- const char* tmp_buf;
- size_t buf_size = 1024;
- char* buf_ptr = 0;
- pvl_elem itr;
-
-/* RFC 2445 explicitly says that the newline is *ALWAYS* a \r\n (CRLF)!!!! */
-char newline[] = "\r\n";
-/* WIN32 automatically adds the \r, Anybody else need it?
-#ifdef ICAL_UNIX_NEWLINE
- char newline[] = "\n";
-#else
- char newline[] = "\r\n";
-#endif
-*/
-
- icalcomponent *c;
- icalproperty *p;
- icalcomponent_kind kind = icalcomponent_isa(impl);
-
- const char* kind_string;
-
- buf = icalmemory_new_buffer(buf_size);
- buf_ptr = buf;
-
- icalerror_check_arg_rz( (impl!=0), "component");
- icalerror_check_arg_rz( (kind!=ICAL_NO_COMPONENT), "component kind is ICAL_NO_COMPONENT");
-
- kind_string = icalcomponent_kind_to_string(kind);
-
- icalerror_check_arg_rz( (kind_string!=0),"Unknown kind of component");
-
- icalmemory_append_string(&buf, &buf_ptr, &buf_size, "BEGIN:");
- icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
- icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
-
-
-
- for( itr = pvl_head(impl->properties);
- itr != 0;
- itr = pvl_next(itr))
- {
- p = (icalproperty*)pvl_data(itr);
-
- icalerror_assert((p!=0),"Got a null property");
- tmp_buf = icalproperty_as_ical_string(p);
-
- icalmemory_append_string(&buf, &buf_ptr, &buf_size, tmp_buf);
- }
-
-
- for( itr = pvl_head(impl->components);
- itr != 0;
- itr = pvl_next(itr))
- {
- c = (icalcomponent*)pvl_data(itr);
-
- tmp_buf = icalcomponent_as_ical_string(c);
-
- icalmemory_append_string(&buf, &buf_ptr, &buf_size, tmp_buf);
-
- }
-
- icalmemory_append_string(&buf, &buf_ptr, &buf_size, "END:");
- icalmemory_append_string(&buf, &buf_ptr, &buf_size,
- icalcomponent_kind_to_string(kind));
- icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
- icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
-
- out_buf = icalmemory_tmp_copy(buf);
- free(buf);
-
- return out_buf;
-}
-
-
-int
-icalcomponent_is_valid (icalcomponent* component)
-{
- if ( (strcmp(component->id,"comp") == 0) &&
- component->kind != ICAL_NO_COMPONENT){
- return 1;
- } else {
- return 0;
- }
-
-}
-
-
-icalcomponent_kind
-icalcomponent_isa (const icalcomponent* component)
-{
- icalerror_check_arg_rx( (component!=0), "component", ICAL_NO_COMPONENT);
-
- if(component != 0)
- {
- return component->kind;
- }
-
- return ICAL_NO_COMPONENT;
-}
-
-
-int
-icalcomponent_isa_component (void* component)
-{
- icalcomponent *impl = component;
-
- icalerror_check_arg_rz( (component!=0), "component");
-
- if (strcmp(impl->id,"comp") == 0) {
- return 1;
- } else {
- return 0;
- }
-
-}
-
-void
-icalcomponent_add_property (icalcomponent* component, icalproperty* property)
-{
- icalerror_check_arg_rv( (component!=0), "component");
- icalerror_check_arg_rv( (property!=0), "property");
-
- icalerror_assert( (!icalproperty_get_parent(property)),"The property has already been added to a component. Remove the property with icalcomponent_remove_property before calling icalcomponent_add_property");
-
- icalproperty_set_parent(property,component);
-
- pvl_push(component->properties,property);
-}
-
-
-void
-icalcomponent_remove_property (icalcomponent* component, icalproperty* property)
-{
- pvl_elem itr, next_itr;
-
- icalerror_check_arg_rv( (component!=0), "component");
- icalerror_check_arg_rv( (property!=0), "property");
-
- icalerror_assert( (icalproperty_get_parent(property)),"The property is not a member of a component");
-
-
- for( itr = pvl_head(component->properties);
- itr != 0;
- itr = next_itr)
- {
- next_itr = pvl_next(itr);
-
- if( pvl_data(itr) == (void*)property ){
-
- if (component->property_iterator == itr){
- component->property_iterator = pvl_next(itr);
- }
-
- pvl_remove( component->properties, itr);
- icalproperty_set_parent(property,0);
- }
- }
-}
-
-int
-icalcomponent_count_properties (icalcomponent* component,
- icalproperty_kind kind)
-{
- int count=0;
- pvl_elem itr;
-
- icalerror_check_arg_rz( (component!=0), "component");
-
- for( itr = pvl_head(component->properties);
- itr != 0;
- itr = pvl_next(itr))
- {
- if(kind == icalproperty_isa((icalproperty*)pvl_data(itr)) ||
- kind == ICAL_ANY_PROPERTY){
- count++;
- }
- }
-
-
- return count;
-
-}
-
-icalproperty* icalcomponent_get_current_property (icalcomponent* component)
-{
- icalerror_check_arg_rz( (component!=0),"component");
-
- if ((component->property_iterator==0)){
- return 0;
- }
-
- return (icalproperty*) pvl_data(component->property_iterator);
-}
-
-icalproperty*
-icalcomponent_get_first_property (icalcomponent* c, icalproperty_kind kind)
-{
- icalerror_check_arg_rz( (c!=0),"component");
-
- for( c->property_iterator = pvl_head(c->properties);
- c->property_iterator != 0;
- c->property_iterator = pvl_next(c->property_iterator)) {
-
- icalproperty *p = (icalproperty*) pvl_data(c->property_iterator);
-
- if (icalproperty_isa(p) == kind || kind == ICAL_ANY_PROPERTY) {
-
- return p;
- }
- }
- return 0;
-}
-
-icalproperty*
-icalcomponent_get_next_property (icalcomponent* c, icalproperty_kind kind)
-{
- icalerror_check_arg_rz( (c!=0),"component");
-
- if (c->property_iterator == 0){
- return 0;
- }
-
- for( c->property_iterator = pvl_next(c->property_iterator);
- c->property_iterator != 0;
- c->property_iterator = pvl_next(c->property_iterator)) {
-
- icalproperty *p = (icalproperty*) pvl_data(c->property_iterator);
-
- if (icalproperty_isa(p) == kind || kind == ICAL_ANY_PROPERTY) {
-
- return p;
- }
- }
-
- return 0;
-}
-
-
-icalproperty**
-icalcomponent_get_properties (icalcomponent* component, icalproperty_kind kind);
-
-
-void
-icalcomponent_add_component (icalcomponent* parent, icalcomponent* child)
-{
- icalerror_check_arg_rv( (parent!=0), "parent");
- icalerror_check_arg_rv( (child!=0), "child");
-
- if (child->parent !=0) {
- icalerror_set_errno(ICAL_USAGE_ERROR);
- }
-
- child->parent = parent;
-
- pvl_push(parent->components,child);
-
- /* If the new component is a VTIMEZONE, add it to our array. */
- if (child->kind == ICAL_VTIMEZONE_COMPONENT) {
- /* FIXME: Currently we are also creating this array when loading in
- a builtin VTIMEZONE, when we don't need it. */
- if (!parent->timezones)
- parent->timezones = icaltimezone_array_new ();
-
- icaltimezone_array_append_from_vtimezone (parent->timezones, child);
-
- /* Flag that we need to sort it before doing any binary searches. */
- parent->timezones_sorted = 0;
- }
-}
-
-
-void
-icalcomponent_remove_component (icalcomponent* parent, icalcomponent* child)
-{
- pvl_elem itr, next_itr;
-
- icalerror_check_arg_rv( (parent!=0), "parent");
- icalerror_check_arg_rv( (child!=0), "child");
-
- /* If the component is a VTIMEZONE, remove it from our array as well. */
- if (child->kind == ICAL_VTIMEZONE_COMPONENT) {
- icaltimezone *zone;
- int i, num_elements;
-
- num_elements = parent->timezones ? parent->timezones->num_elements : 0;
- for (i = 0; i < num_elements; i++) {
- zone = icalarray_element_at (parent->timezones, i);
- if (icaltimezone_get_component (zone) == child) {
- icaltimezone_free (zone, 0);
- icalarray_remove_element_at (parent->timezones, i);
- break;
- }
- }
- }
-
- for( itr = pvl_head(parent->components);
- itr != 0;
- itr = next_itr)
- {
- next_itr = pvl_next(itr);
-
- if( pvl_data(itr) == (void*)child ){
-
- if (parent->component_iterator == itr){
- /* Don't let the current iterator become invalid */
-
- /* HACK. The semantics for this are troubling. */
- parent->component_iterator =
- pvl_next(parent->component_iterator);
-
- }
- pvl_remove( parent->components, itr);
- child->parent = 0;
- break;
- }
- }
-}
-
-
-int
-icalcomponent_count_components (icalcomponent* component,
- icalcomponent_kind kind)
-{
- int count=0;
- pvl_elem itr;
-
- icalerror_check_arg_rz( (component!=0), "component");
-
- for( itr = pvl_head(component->components);
- itr != 0;
- itr = pvl_next(itr))
- {
- if(kind == icalcomponent_isa((icalcomponent*)pvl_data(itr)) ||
- kind == ICAL_ANY_COMPONENT){
- count++;
- }
- }
-
- return count;
-}
-
-icalcomponent*
-icalcomponent_get_current_component(icalcomponent* component)
-{
- icalerror_check_arg_rz( (component!=0),"component");
-
- if (component->component_iterator == 0){
- return 0;
- }
-
- return (icalcomponent*) pvl_data(component->component_iterator);
-}
-
-icalcomponent*
-icalcomponent_get_first_component (icalcomponent* c,
- icalcomponent_kind kind)
-{
- icalerror_check_arg_rz( (c!=0),"component");
-
- for( c->component_iterator = pvl_head(c->components);
- c->component_iterator != 0;
- c->component_iterator = pvl_next(c->component_iterator)) {
-
- icalcomponent *p = (icalcomponent*) pvl_data(c->component_iterator);
-
- if (icalcomponent_isa(p) == kind || kind == ICAL_ANY_COMPONENT) {
-
- return p;
- }
- }
-
- return 0;
-}
-
-
-icalcomponent*
-icalcomponent_get_next_component (icalcomponent* c, icalcomponent_kind kind)
-{
- icalerror_check_arg_rz( (c!=0),"component");
-
- if (c->component_iterator == 0){
- return 0;
- }
-
- for( c->component_iterator = pvl_next(c->component_iterator);
- c->component_iterator != 0;
- c->component_iterator = pvl_next(c->component_iterator)) {
-
- icalcomponent *p = (icalcomponent*) pvl_data(c->component_iterator);
-
- if (icalcomponent_isa(p) == kind || kind == ICAL_ANY_COMPONENT) {
-
- return p;
- }
- }
-
- return 0;
-}
-
-icalcomponent* icalcomponent_get_first_real_component(icalcomponent *c)
-{
- icalcomponent *comp;
-
- for(comp = icalcomponent_get_first_component(c,ICAL_ANY_COMPONENT);
- comp != 0;
- comp = icalcomponent_get_next_component(c,ICAL_ANY_COMPONENT)){
-
- icalcomponent_kind kind = icalcomponent_isa(comp);
-
- if(kind == ICAL_VEVENT_COMPONENT ||
- kind == ICAL_VTODO_COMPONENT ||
- kind == ICAL_VJOURNAL_COMPONENT ||
- kind == ICAL_VFREEBUSY_COMPONENT ||
- kind == ICAL_VQUERY_COMPONENT ||
- kind == ICAL_VAGENDA_COMPONENT){
- return comp;
- }
- }
- return 0;
-}
-
-
-/** @brief Get the timespan covered by this component, in UTC
- * (deprecated)
- *
- * see icalcomponent_foreach_recurrence() for a better way to
- * extract spans from an component.
- *
- * This method can be called on either a VCALENDAR or any real
- * component. If the VCALENDAR contains no real component, but
- * contains a VTIMEZONE, we return that span instead.
- * This might not be a desirable behavior; we keep it for now
- * for backward compatibility, but it might be deprecated at a
- * future time.
- *
- * FIXME this API needs to be clarified. DTEND is defined as the
- * first available time after the end of this event, so the span
- * should actually end 1 second before DTEND.
- */
-
-icaltime_span icalcomponent_get_span(icalcomponent* comp)
-{
- icalcomponent *inner;
- icalcomponent_kind kind;
- icaltime_span span;
- struct icaltimetype start, end;
-
- span.start = 0;
- span.end = 0;
- span.is_busy= 1;
-
- /* initial Error checking */
- if (comp == NULL) {
- return span;
- }
-
- /* FIXME this might go away */
- kind = icalcomponent_isa(comp);
- if(kind == ICAL_VCALENDAR_COMPONENT){
- inner = icalcomponent_get_first_real_component(comp);
-
- /* Maybe there is a VTIMEZONE in there */
- if (inner == 0){
- inner = icalcomponent_get_first_component(comp,
- ICAL_VTIMEZONE_COMPONENT);
- }
-
- } else {
- inner = comp;
- }
-
- if (inner == 0){
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- /*icalerror_warn("icalcomponent_get_span: no component specified, or empty VCALENDAR component");*/
- return span;
- }
-
- kind = icalcomponent_isa(inner);
-
- if( !( kind == ICAL_VEVENT_COMPONENT ||
- kind == ICAL_VJOURNAL_COMPONENT ||
- kind == ICAL_VTODO_COMPONENT ||
- kind == ICAL_VFREEBUSY_COMPONENT )) {
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- /*icalerror_warn("icalcomponent_get_span: no component specified, or empty VCALENDAR component");*/
- return span;
-
- }
-
- /* Get to work. starting with DTSTART */
- start = icalcomponent_get_dtstart(comp);
- if (icaltime_is_null_time(start)) {
- return span;
- }
- span.start = icaltime_as_timet_with_zone(start,
- icaltimezone_get_utc_timezone());
-
- /* The end time could be specified as either a DTEND or a DURATION */
- /* icalcomponent_get_dtend takes care of these cases. */
- end = icalcomponent_get_dtend(comp);
- if (icaltime_is_null_time(end)) {
- if (!icaltime_is_date(start)) {
- /* If dtstart is a DATE-TIME and there is no DTEND nor DURATION
- it takes no time */
- span.start = 0;
- return span;
- } else {
- end = start;
- }
- }
-
- span.end = icaltime_as_timet_with_zone(end,
- icaltimezone_get_utc_timezone());
- if (icaltime_is_date(start)) {
- /* Until the end of the day*/
- span.end += 60*60*24 - 1;
- }
-
- return span;
-
-}
-
-/**
- * Decide if this recurrance is acceptable
- *
- * @param comp A valid icalcomponent.
- * @param dtstart The base dtstart value for this component.
- * @param recurtime The time to test against.
- *
- * @return true if the recurrence value is excluded, false otherwise.
- *
- * This function decides if a specific recurrence value is
- * excluded by EXRULE or EXDATE properties.
- *
- * It's not the most efficient code. You might get better performance
- * if you assume that recurtime is always increasing for each
- * call. Then you could:
- *
- * - sort the EXDATE values
- * - save the state of each EXRULE iterator for the next call.
- *
- * In this case though you don't need to worry how you call this
- * function. It will always return the correct result.
- */
-
-int icalproperty_recurrence_is_excluded(icalcomponent *comp,
- struct icaltimetype *dtstart,
- struct icaltimetype *recurtime) {
- icalproperty *exdate, *exrule;
-
- if (comp == NULL ||
- dtstart == NULL ||
- recurtime == NULL ||
- icaltime_is_null_time(*recurtime))
- /* BAD DATA */
- return 1;
-
- /** first test against the exdate values **/
- for (exdate = icalcomponent_get_first_property(comp,ICAL_EXDATE_PROPERTY);
- exdate != NULL;
- exdate = icalcomponent_get_next_property(comp,ICAL_EXDATE_PROPERTY)) {
-
- struct icaltimetype exdatetime = icalproperty_get_exdate(exdate);
-
- if (icaltime_compare(*recurtime, exdatetime) == 0) {
- /** MATCHED **/
- return 1;
- }
- }
-
- /** Now test against the EXRULEs **/
- for (exrule = icalcomponent_get_first_property(comp,ICAL_EXRULE_PROPERTY);
- exrule != NULL;
- exrule = icalcomponent_get_next_property(comp,ICAL_EXRULE_PROPERTY)) {
-
- struct icalrecurrencetype recur = icalproperty_get_exrule(exrule);
- icalrecur_iterator *exrule_itr = icalrecur_iterator_new(recur, *dtstart);
- struct icaltimetype exrule_time;
-
- while (1) {
- int result;
- exrule_time = icalrecur_iterator_next(exrule_itr);
-
- if (icaltime_is_null_time(exrule_time))
- break;
-
- result = icaltime_compare(*recurtime, exrule_time);
- if (result == 0) {
- icalrecur_iterator_free(exrule_itr);
- return 1; /** MATCH **/
- }
- if (result == 1)
- break; /** exrule_time > recurtime **/
- }
-
- icalrecur_iterator_free(exrule_itr);
- }
-
- return 0; /** no matches **/
-}
-
-/**
- * @brief Return the busy status based on the TRANSP property.
- *
- * @param comp A valid icalcomponent.
- *
- * @return 1 if the event is a busy item, 0 if it is not.
- */
-
-static int icalcomponent_is_busy(icalcomponent *comp) {
- icalproperty *transp;
- enum icalproperty_status status;
- int ret = 1;
-
- /** @todo check access control here, converting busy->free if the
- permissions do not allow access... */
-
- /* Is this a busy time? Check the TRANSP property */
- transp = icalcomponent_get_first_property(comp, ICAL_TRANSP_PROPERTY);
-
- if (transp) {
- icalvalue *transp_val = icalproperty_get_value(transp);
-
- switch (icalvalue_get_transp(transp_val)) {
- case ICAL_TRANSP_OPAQUE:
- case ICAL_TRANSP_OPAQUENOCONFLICT:
- case ICAL_TRANSP_NONE:
- ret = 1;
- break;
- case ICAL_TRANSP_TRANSPARENT:
- case ICAL_TRANSP_TRANSPARENTNOCONFLICT:
- ret = 0;
- break;
- default:
- ret = 0;
- break;
- }
- }
- status = icalcomponent_get_status(comp);
- if (ret && status) {
- switch (status) {
- case ICAL_STATUS_CANCELLED:
- case ICAL_STATUS_TENTATIVE:
- ret = 0;
- break;
- default:
- break;
- }
- }
- return(ret);
-}
-
-
-
-
-/**
- * @brief cycle through all recurrances of an event
- *
- * @param comp A valid VEVENT component
- * @param start Ignore timespans before this
- * @param end Ignore timespans after this
- * @param callback Function called for each timespan within the range
- * @param callback_data Pointer passed back to the callback function
- *
- * This function will call the specified callback function for once
- * for the base value of DTSTART, and foreach recurring date/time
- * value.
- *
- * It will filter out events that are specified as an EXDATE or an EXRULE.
- *
- * @todo We do not filter out duplicate RRULES/RDATES
- * @todo We do not handle RDATEs with explicit periods
- */
-
-void icalcomponent_foreach_recurrence(icalcomponent* comp,
- struct icaltimetype start,
- struct icaltimetype end,
- void (*callback)(icalcomponent *comp,
- struct icaltime_span *span,
- void *data),
- void *callback_data)
-{
- struct icaltimetype dtstart, dtend;
- icaltime_span recurspan, basespan, limit_span;
- time_t limit_start, limit_end;
- int dtduration;
- icalproperty *rrule, *rdate;
- struct icaldurationtype dur;
- pvl_elem property_iterator; /* for saving the iterator */
-
- if (comp == NULL || callback == NULL)
- return;
-
- dtstart = icalcomponent_get_dtstart(comp);
-
- if (icaltime_is_null_time(dtstart))
- return;
-
-
- /* The end time could be specified as either a DTEND or a DURATION */
- /* icalcomponent_get_dtend takes care of these cases. */
- dtend = icalcomponent_get_dtend(comp);
-
- /* Now set up the base span for this item, corresponding to the
- base DTSTART and DTEND */
- basespan = icaltime_span_new(dtstart, dtend, 1);
-
- basespan.is_busy = icalcomponent_is_busy(comp);
-
-
- /** Calculate the ceiling and floor values.. **/
- limit_start = icaltime_as_timet_with_zone(start, icaltimezone_get_utc_timezone());
- if (!icaltime_is_null_time(end))
- limit_end = icaltime_as_timet_with_zone(end, icaltimezone_get_utc_timezone());
- else
- limit_end = INT_MAX; /* max 32 bit time_t */
-
- limit_span.start = limit_start;
- limit_span.end = limit_end;
-
-
- /* Do the callback for the initial DTSTART entry */
-
- if (!icalproperty_recurrence_is_excluded(comp, &dtstart, &dtstart)) {
- /** call callback action **/
- if (icaltime_span_overlaps(&basespan, &limit_span))
- (*callback) (comp, &basespan, callback_data);
- }
-
- recurspan = basespan;
- dtduration = basespan.end - basespan.start;
-
- /* Now cycle through the rrule entries */
- for (rrule = icalcomponent_get_first_property(comp,ICAL_RRULE_PROPERTY);
- rrule != NULL;
- rrule = icalcomponent_get_next_property(comp,ICAL_RRULE_PROPERTY)) {
-
- struct icalrecurrencetype recur = icalproperty_get_rrule(rrule);
- icalrecur_iterator *rrule_itr = icalrecur_iterator_new(recur, dtstart);
- struct icaltimetype rrule_time = icalrecur_iterator_next(rrule_itr);
- /** note that icalrecur_iterator_next always returns dtstart
- the first time.. **/
-
- while (1) {
- rrule_time = icalrecur_iterator_next(rrule_itr);
-
- if (icaltime_is_null_time(rrule_time))
- break;
-
- dur = icaltime_subtract(rrule_time, dtstart);
-
- recurspan.start = basespan.start + icaldurationtype_as_int(dur);
- recurspan.end = recurspan.start + dtduration;
-
- /** save the iterator ICK! **/
- property_iterator = comp->property_iterator;
-
- if (!icalproperty_recurrence_is_excluded(comp, &dtstart, &rrule_time)) {
- /** call callback action **/
- if (icaltime_span_overlaps(&recurspan, &limit_span))
- (*callback) (comp, &recurspan, callback_data);
- }
- comp->property_iterator = property_iterator;
- } /* end of iteration over a specific RRULE */
-
- icalrecur_iterator_free(rrule_itr);
- } /* end of RRULE loop */
-
-
- /** Now process RDATE entries **/
- for (rdate = icalcomponent_get_first_property(comp,ICAL_RDATE_PROPERTY);
- rdate != NULL;
- rdate = icalcomponent_get_next_property(comp,ICAL_RDATE_PROPERTY)) {
-
- struct icaldatetimeperiodtype rdate_period = icalproperty_get_rdate(rdate);
-
- /** RDATES can specify raw datetimes, periods, or dates.
- we only support raw datetimes for now..
-
- @todo Add support for other types **/
-
- if (icaltime_is_null_time(rdate_period.time))
- continue;
-
- dur = icaltime_subtract(rdate_period.time, dtstart);
-
- recurspan.start = basespan.start + icaldurationtype_as_int(dur);
- recurspan.end = recurspan.start + dtduration;
-
- /** save the iterator ICK! **/
- property_iterator = comp->property_iterator;
-
- if (!icalproperty_recurrence_is_excluded(comp, &dtstart, &rdate_period.time)) {
- /** call callback action **/
- (*callback) (comp, &recurspan, callback_data);
- }
- comp->property_iterator = property_iterator;
- }
-}
-
-
-
-int icalcomponent_check_restrictions(icalcomponent* comp){
- icalerror_check_arg_rz(comp!=0,"comp");
- return icalrestriction_check(comp);
-}
-
-/** @brief returns the number of errors encountered parsing the data
- *
- * This function counts the number times the X-LIC-ERROR occurs
- * in the data structure.
- */
-
-int icalcomponent_count_errors(icalcomponent* component)
-{
- int errors = 0;
- icalproperty *p;
- icalcomponent *c;
- pvl_elem itr;
-
- for( itr = pvl_head(component->properties);
- itr != 0;
- itr = pvl_next(itr))
- {
- p = (icalproperty*)pvl_data(itr);
-
- if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
- {
- errors++;
- }
- }
-
-
- for( itr = pvl_head(component->components);
- itr != 0;
- itr = pvl_next(itr))
- {
- c = (icalcomponent*)pvl_data(itr);
-
- errors += icalcomponent_count_errors(c);
-
- }
-
- return errors;
-}
-
-
-void icalcomponent_strip_errors(icalcomponent* component)
-{
- icalproperty *p;
- icalcomponent *c;
- pvl_elem itr, next_itr;
-
- for( itr = pvl_head(component->properties);
- itr != 0;
- itr = next_itr)
- {
- p = (icalproperty*)pvl_data(itr);
- next_itr = pvl_next(itr);
-
- if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
- {
- icalcomponent_remove_property(component,p);
- }
- }
-
- for( itr = pvl_head(component->components);
- itr != 0;
- itr = pvl_next(itr))
- {
- c = (icalcomponent*)pvl_data(itr);
- icalcomponent_strip_errors(c);
- }
-}
-
-/* Hack. This will change the state of the iterators */
-void icalcomponent_convert_errors(icalcomponent* component)
-{
- icalproperty *p, *next_p;
- icalcomponent *c;
-
- for(p = icalcomponent_get_first_property(component,ICAL_ANY_PROPERTY);
- p != 0;
- p = next_p){
-
- next_p = icalcomponent_get_next_property(component,ICAL_ANY_PROPERTY);
-
- if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
- {
- struct icalreqstattype rst;
- icalparameter *param = icalproperty_get_first_parameter
- (p,ICAL_XLICERRORTYPE_PARAMETER);
-
- rst.code = ICAL_UNKNOWN_STATUS;
- rst.desc = 0;
-
- switch(icalparameter_get_xlicerrortype(param)){
-
- case ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR: {
- rst.code = ICAL_3_2_INVPARAM_STATUS;
- break;
- }
- case ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR: {
- rst.code = ICAL_3_3_INVPARAMVAL_STATUS;
- break;
- }
- case ICAL_XLICERRORTYPE_PROPERTYPARSEERROR: {
- rst.code = ICAL_3_0_INVPROPNAME_STATUS;
- break;
- }
- case ICAL_XLICERRORTYPE_VALUEPARSEERROR: {
- rst.code = ICAL_3_1_INVPROPVAL_STATUS;
- break;
- }
- case ICAL_XLICERRORTYPE_COMPONENTPARSEERROR: {
- rst.code = ICAL_3_4_INVCOMP_STATUS;
- break;
- }
-
- default: {
- break;
- }
- }
- if (rst.code != ICAL_UNKNOWN_STATUS){
-
- rst.debug = icalproperty_get_xlicerror(p);
- icalcomponent_add_property(component,
- icalproperty_new_requeststatus(rst));
-
- icalcomponent_remove_property(component,p);
- }
- }
- }
-
- for(c = icalcomponent_get_first_component(component,ICAL_ANY_COMPONENT);
- c != 0;
- c = icalcomponent_get_next_component(component,ICAL_ANY_COMPONENT)){
-
- icalcomponent_convert_errors(c);
- }
-}
-
-
-icalcomponent* icalcomponent_get_parent(icalcomponent* component)
-{
- return component->parent;
-}
-
-void icalcomponent_set_parent(icalcomponent* component, icalcomponent* parent)
-{
- component->parent = parent;
-}
-
-icalcompiter icalcompiter_null = {ICAL_NO_COMPONENT,0};
-
-
-struct icalcomponent_kind_map {
- icalcomponent_kind kind;
- char name[20];
-};
-
-
-
-static struct icalcomponent_kind_map component_map[] =
-{
- { ICAL_VEVENT_COMPONENT, "VEVENT" },
- { ICAL_VTODO_COMPONENT, "VTODO" },
- { ICAL_VJOURNAL_COMPONENT, "VJOURNAL" },
- { ICAL_VCALENDAR_COMPONENT, "VCALENDAR" },
- { ICAL_VAGENDA_COMPONENT, "VAGENDA" },
- { ICAL_VFREEBUSY_COMPONENT, "VFREEBUSY" },
- { ICAL_VTIMEZONE_COMPONENT, "VTIMEZONE" },
- { ICAL_VALARM_COMPONENT, "VALARM" },
- { ICAL_XSTANDARD_COMPONENT, "STANDARD" }, /*These are part of RFC2445 */
- { ICAL_XDAYLIGHT_COMPONENT, "DAYLIGHT" }, /*but are not really components*/
- { ICAL_X_COMPONENT, "X" },
- { ICAL_VSCHEDULE_COMPONENT, "SCHEDULE" },
-
- /* CAP components */
- { ICAL_VQUERY_COMPONENT, "VQUERY" },
- { ICAL_VCAR_COMPONENT, "VCAR" },
- { ICAL_VCOMMAND_COMPONENT, "VCOMMAND" },
-
- /* libical private components */
- { ICAL_XLICINVALID_COMPONENT, "X-LIC-UNKNOWN" },
- { ICAL_XLICMIMEPART_COMPONENT, "X-LIC-MIME-PART" },
- { ICAL_ANY_COMPONENT, "ANY" },
- { ICAL_XROOT_COMPONENT, "XROOT" },
-
- /* End of list */
- { ICAL_NO_COMPONENT, "" },
-};
-
-
-int icalcomponent_kind_is_valid(const icalcomponent_kind kind)
-{
- int i = 0;
- do {
- if (component_map[i].kind == kind)
- return 1;
- } while (component_map[i++].kind != ICAL_NO_COMPONENT);
-
- return 0;
-}
-
-const char* icalcomponent_kind_to_string(icalcomponent_kind kind)
-{
- int i;
-
- for (i=0; component_map[i].kind != ICAL_NO_COMPONENT; i++) {
- if (component_map[i].kind == kind) {
- return component_map[i].name;
- }
- }
-
- return 0;
-
-}
-
-icalcomponent_kind icalcomponent_string_to_kind(const char* string)
-{
- int i;
-
- if (string ==0 ) {
- return ICAL_NO_COMPONENT;
- }
-
- for (i=0; component_map[i].kind != ICAL_NO_COMPONENT; i++) {
- if (strcasecmp(component_map[i].name, string) == 0) {
- return component_map[i].kind;
- }
- }
-
- return ICAL_NO_COMPONENT;
-}
-
-
-
-icalcompiter
-icalcomponent_begin_component(icalcomponent* component,icalcomponent_kind kind)
-{
- icalcompiter itr;
- pvl_elem i;
-
- itr.kind = kind;
- itr.iter = NULL;
-
- icalerror_check_arg_re(component!=0,"component",icalcompiter_null);
-
- for( i = pvl_head(component->components); i != 0; i = pvl_next(i)) {
-
- icalcomponent *c = (icalcomponent*) pvl_data(i);
-
- if (icalcomponent_isa(c) == kind || kind == ICAL_ANY_COMPONENT) {
-
- itr.iter = i;
-
- return itr;
- }
- }
-
- return icalcompiter_null;
-}
-
-icalcompiter
-icalcomponent_end_component(icalcomponent* component,icalcomponent_kind kind)
-{
- icalcompiter itr;
- pvl_elem i;
-
- itr.kind = kind;
-
- icalerror_check_arg_re(component!=0,"component",icalcompiter_null);
-
- for( i = pvl_tail(component->components); i != 0; i = pvl_prior(i)) {
-
- icalcomponent *c = (icalcomponent*) pvl_data(i);
-
- if (icalcomponent_isa(c) == kind || kind == ICAL_ANY_COMPONENT) {
-
- itr.iter = pvl_next(i);
-
- return itr;
- }
- }
-
- return icalcompiter_null;;
-}
-
-
-icalcomponent* icalcompiter_next(icalcompiter* i)
-{
- if (i->iter == 0){
- return 0;
- }
-
- icalerror_check_arg_rz( (i!=0),"i");
-
- for( i->iter = pvl_next(i->iter);
- i->iter != 0;
- i->iter = pvl_next(i->iter)) {
-
- icalcomponent *c = (icalcomponent*) pvl_data(i->iter);
-
- if (icalcomponent_isa(c) == i->kind
- || i->kind == ICAL_ANY_COMPONENT) {
-
- return icalcompiter_deref(i);;
- }
- }
-
- return 0;
-
-}
-
-icalcomponent* icalcompiter_prior(icalcompiter* i)
-{
- if (i->iter == 0){
- return 0;
- }
-
- for( i->iter = pvl_prior(i->iter);
- i->iter != 0;
- i->iter = pvl_prior(i->iter)) {
-
- icalcomponent *c = (icalcomponent*) pvl_data(i->iter);
-
- if (icalcomponent_isa(c) == i->kind
- || i->kind == ICAL_ANY_COMPONENT) {
-
- return icalcompiter_deref(i);;
- }
- }
-
- return 0;
-
-}
-icalcomponent* icalcompiter_deref(icalcompiter* i)
-{
- if(i->iter ==0){
- return 0;
- }
-
- return pvl_data(i->iter);
-}
-
-icalcomponent* icalcomponent_get_inner(icalcomponent* comp)
-{
- if (icalcomponent_isa(comp) == ICAL_VCALENDAR_COMPONENT){
- return icalcomponent_get_first_real_component(comp);
- } else {
- return comp;
- }
-}
-
-/** @brief sets the METHOD property to the given method
- */
-
-void icalcomponent_set_method(icalcomponent* comp, icalproperty_method method)
-{
- icalproperty *prop
- = icalcomponent_get_first_property(comp, ICAL_METHOD_PROPERTY);
-
-
- if (prop == 0){
- prop = icalproperty_new_method(method);
- icalcomponent_add_property(comp, prop);
- }
-
- icalproperty_set_method(prop,method);
-
-}
-
-/** @brief returns the METHOD property
- */
-
-icalproperty_method icalcomponent_get_method(icalcomponent* comp)
-{
- icalproperty *prop
- = icalcomponent_get_first_property(comp,ICAL_METHOD_PROPERTY);
-
- if (prop == 0){
- return ICAL_METHOD_NONE;
- }
-
- return icalproperty_get_method(prop);
-}
-
-#define ICALSETUPSET(p_kind) \
- icalcomponent *inner; \
- icalproperty *prop; \
- icalerror_check_arg_rv(comp!=0,"comp");\
- inner = icalcomponent_get_inner(comp); \
- if(inner == 0){\
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);\
- return;\
- }\
- prop = icalcomponent_get_first_property(inner, p_kind);
-
-
-/** @brief Set DTSTART property to given icaltime
- *
- * This method respects the icaltime type (DATE vs DATE-TIME) and
- * timezone (or lack thereof).
- */
-void icalcomponent_set_dtstart(icalcomponent* comp, struct icaltimetype v)
-{
- const char *tzid;
- ICALSETUPSET(ICAL_DTSTART_PROPERTY);
-
- if (prop == 0){
- prop = icalproperty_new_dtstart(v);
- icalcomponent_add_property(inner, prop);
- } else {
- icalproperty_remove_parameter_by_kind(prop, ICAL_TZID_PARAMETER);
- }
-
- icalproperty_set_dtstart(prop,v);
-
- if ((tzid = icaltime_get_tzid(v)) != NULL && !icaltime_is_utc(v)) {
- icalproperty_add_parameter(prop, icalparameter_new_tzid(tzid));
- }
-}
-
-/** @brief Get a DATE or DATE-TIME property as an icaltime
- *
- * If the property is a DATE-TIME with a timezone parameter and a
- * corresponding VTIMEZONE is present in the component, the
- * returned component will already be in the correct timezone;
- * otherwise the caller is responsible for converting it.
- *
- * FIXME this is useless until we can flag the failure
- */
-static struct icaltimetype
-icalcomponent_get_datetime(icalcomponent *comp, icalproperty *prop) {
-
- icalparameter *param;
- struct icaltimetype ret;
-
- ret = icalvalue_get_datetime(icalproperty_get_value(prop));
-
- if ((param = icalproperty_get_first_parameter(prop, ICAL_TZID_PARAMETER))
- != NULL) {
- const char *tzid = icalparameter_get_tzid(param);
- icaltimezone *tz;
-
- if ((tz = icalcomponent_get_timezone(comp, tzid)) != NULL) {
- icaltime_set_timezone(&ret, tz);
- }
- }
-
- return ret;
-}
-
-/** @brief Get DTSTART property as an icaltime
- *
- * If DTSTART is a DATE-TIME with a timezone parameter and a
- * corresponding VTIMEZONE is present in the component, the
- * returned component will already be in the correct timezone;
- * otherwise the caller is responsible for converting it.
- *
- * FIXME this is useless until we can flag the failure
- */
-struct icaltimetype icalcomponent_get_dtstart(icalcomponent* comp)
-{
- icalcomponent *inner = icalcomponent_get_inner(comp);
- icalproperty *prop;
-
- prop = icalcomponent_get_first_property(inner,ICAL_DTSTART_PROPERTY);
- if (prop == 0){
- return icaltime_null_time();
- }
-
- return icalcomponent_get_datetime(comp, prop);
-}
-
-/** @brief Get DTEND property as an icaltime
- *
- * If a DTEND property is not present but a DURATION is, we use
- * that to determine the proper end.
- *
- * If DTSTART is a DATE-TIME with a timezone parameter and a
- * corresponding VTIMEZONE is present in the component, the
- * returned component will already be in the correct timezone;
- * otherwise the caller is responsible for converting it.
- *
- * FIXME this is useless until we can flag the failure
- */
-struct icaltimetype icalcomponent_get_dtend(icalcomponent* comp)
-{
- icalcomponent *inner = icalcomponent_get_inner(comp);
- icalproperty *end_prop
- = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
- icalproperty *dur_prop
- = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
- struct icaltimetype ret = icaltime_null_time();
-
- if ( end_prop != 0) {
- ret = icalcomponent_get_datetime(comp, end_prop);
- } else if ( dur_prop != 0) {
-
- struct icaltimetype start =
- icalcomponent_get_dtstart(inner);
- struct icaldurationtype duration =
- icalproperty_get_duration(dur_prop);
-
- struct icaltimetype end = icaltime_add(start,duration);
-
- ret = end;
- }
-
- return ret;
-}
-
-/** @brief Set DTEND property to given icaltime
- *
- * This method respects the icaltime type (DATE vs DATE-TIME) and
- * timezone (or lack thereof).
- *
- * This also checks that a DURATION property isn't already there,
- * and returns an error if it is. It's the caller's responsibility
- * to remove it.
- */
-void icalcomponent_set_dtend(icalcomponent* comp, struct icaltimetype v)
-{
- const char *tzid;
- ICALSETUPSET(ICAL_DTEND_PROPERTY);
-
- if (icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY)
- != NULL) {
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- return;
- }
-
- if (prop == 0) {
- prop = icalproperty_new_dtend(v);
- icalcomponent_add_property(inner, prop);
- } else {
- icalproperty_remove_parameter_by_kind(prop, ICAL_TZID_PARAMETER);
- }
-
- icalproperty_set_dtend(prop,v);
-
- if ((tzid = icaltime_get_tzid(v)) != NULL && !icaltime_is_utc(v)) {
- icalproperty_add_parameter(prop, icalparameter_new_tzid(tzid));
- }
-}
-
-/** @brief Set DURATION property to given icalduration
- *
- * This method respects the icaltime type (DATE vs DATE-TIME) and
- * timezone (or lack thereof).
- *
- * This also checks that a DTEND property isn't already there,
- * and returns an error if it is. It's the caller's responsibility
- * to remove it.
- */
-void icalcomponent_set_duration(icalcomponent* comp,
- struct icaldurationtype v)
-{
- ICALSETUPSET(ICAL_DURATION_PROPERTY);
-
- if (icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY) != NULL) {
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- return;
- }
-
- if (prop == 0) {
- prop = icalproperty_new_duration(v);
- icalcomponent_add_property(inner, prop);
- } else {
- icalproperty_set_duration(prop,v);
- }
-}
-
-/** @brief Get DURATION property as an icalduration
- *
- * If a DURATION property is not present but a DTEND is, we use
- * that to determine the proper end.
- */
-struct icaldurationtype icalcomponent_get_duration(icalcomponent* comp)
-{
- icalcomponent *inner = icalcomponent_get_inner(comp);
-
- icalproperty *end_prop
- = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
-
- icalproperty *dur_prop
- = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
-
- struct icaldurationtype ret = icaldurationtype_null_duration();
-
- if ( dur_prop != 0 && end_prop == 0) {
- ret = icalproperty_get_duration(dur_prop);
-
- } else if ( end_prop != 0 && dur_prop == 0) {
- /**
- * FIXME
- * We assume DTSTART and DTEND are not in different time zones.
- * Does the standard actually guarantee this?
- */
- struct icaltimetype start =
- icalcomponent_get_dtstart(inner);
- struct icaltimetype end =
- icalcomponent_get_dtend(inner);
-
- ret = icaltime_subtract(end, start);
- } else {
- /* Error, both duration and dtend have been specified */
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- }
- return ret;
-}
-
-void icalcomponent_set_dtstamp(icalcomponent* comp, struct icaltimetype v)
-{
-
- ICALSETUPSET(ICAL_DTSTAMP_PROPERTY);
-
- if (prop == 0){
- prop = icalproperty_new_dtstamp(v);
- icalcomponent_add_property(inner, prop);
- }
-
- icalproperty_set_dtstamp(prop,v);
-
-}
-
-
-struct icaltimetype icalcomponent_get_dtstamp(icalcomponent* comp)
-{
- icalcomponent *inner = icalcomponent_get_inner(comp);
- icalproperty *prop
- = icalcomponent_get_first_property(inner,ICAL_DTSTAMP_PROPERTY);
-
- if (prop == 0){
- return icaltime_null_time();
- }
-
- return icalproperty_get_dtstamp(prop);
-}
-
-
-void icalcomponent_set_summary(icalcomponent* comp, const char* v)
-{
- ICALSETUPSET(ICAL_SUMMARY_PROPERTY)
-
- if (prop == 0){
- prop = icalproperty_new_summary(v);
- icalcomponent_add_property(inner, prop);
- }
-
- icalproperty_set_summary(prop,v);
-}
-
-
-const char* icalcomponent_get_summary(icalcomponent* comp)
-{
- icalcomponent *inner;
- icalproperty *prop;
- icalerror_check_arg_rz(comp!=0,"comp");
-
- inner = icalcomponent_get_inner(comp);
-
- if(inner == 0){
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- return 0;
- }
-
- prop= icalcomponent_get_first_property(inner,ICAL_SUMMARY_PROPERTY);
-
- if (prop == 0){
- return 0;
- }
-
- return icalproperty_get_summary(prop);
-
-}
-
-void icalcomponent_set_comment(icalcomponent* comp, const char* v)
-{
- ICALSETUPSET(ICAL_COMMENT_PROPERTY);
-
- if (prop == 0){
- prop = icalproperty_new_comment(v);
- icalcomponent_add_property(inner, prop);
- }
-
- icalproperty_set_summary(prop,v);
-
-}
-const char* icalcomponent_get_comment(icalcomponent* comp){
- icalcomponent *inner;
- icalproperty *prop;
- icalerror_check_arg_rz(comp!=0,"comp");
-
- inner = icalcomponent_get_inner(comp);
-
- if(inner == 0){
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- return 0;
- }
-
- prop= icalcomponent_get_first_property(inner,ICAL_COMMENT_PROPERTY);
-
- if (prop == 0){
- return 0;
- }
-
- return icalproperty_get_comment(prop);
-}
-
-void icalcomponent_set_uid(icalcomponent* comp, const char* v)
-{
- ICALSETUPSET(ICAL_UID_PROPERTY);
-
- if (prop == 0){
- prop = icalproperty_new_uid(v);
- icalcomponent_add_property(inner, prop);
- }
-
- icalproperty_set_summary(prop,v);
-
-}
-const char* icalcomponent_get_uid(icalcomponent* comp){
- icalcomponent *inner;
- icalproperty *prop;
- icalerror_check_arg_rz(comp!=0,"comp");
-
- inner = icalcomponent_get_inner(comp);
-
- if(inner == 0){
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- return 0;
- }
-
- prop= icalcomponent_get_first_property(inner,ICAL_UID_PROPERTY);
-
- if (prop == 0){
- return 0;
- }
-
- return icalproperty_get_uid(prop);
-}
-
-void icalcomponent_set_recurrenceid(icalcomponent* comp, struct icaltimetype v)
-{
- ICALSETUPSET(ICAL_RECURRENCEID_PROPERTY);
-
- if (prop == 0){
- prop = icalproperty_new_recurrenceid(v);
- icalcomponent_add_property(inner, prop);
- }
-
- icalproperty_set_recurrenceid(prop,v);
-}
-struct icaltimetype icalcomponent_get_recurrenceid(icalcomponent* comp)
-{
- icalcomponent *inner;
- icalproperty *prop;
- if (comp == 0) {
- icalerror_set_errno(ICAL_BADARG_ERROR);
- return icaltime_null_time();
- }
-
- inner = icalcomponent_get_inner(comp);
-
- if(inner == 0){
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- return icaltime_null_time();
- }
-
- prop= icalcomponent_get_first_property(inner, ICAL_RECURRENCEID_PROPERTY);
-
- if (prop == 0){
- return icaltime_null_time();
- }
-
- return icalproperty_get_recurrenceid(prop);
-}
-
-void icalcomponent_set_description(icalcomponent* comp, const char* v)
-{
- ICALSETUPSET(ICAL_DESCRIPTION_PROPERTY);
-
- if (prop == 0){
- prop = icalproperty_new_description(v);
- icalcomponent_add_property(inner, prop);
- }
-
- icalproperty_set_description(prop,v);
-}
-const char* icalcomponent_get_description(icalcomponent* comp)
-{
- icalcomponent *inner;
- icalproperty *prop;
- icalerror_check_arg_rz(comp!=0,"comp");
-
- inner = icalcomponent_get_inner(comp);
-
- if(inner == 0){
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- return 0;
- }
-
- prop= icalcomponent_get_first_property(inner,ICAL_DESCRIPTION_PROPERTY);
-
- if (prop == 0){
- return 0;
- }
-
- return icalproperty_get_description(prop);
-}
-
-void icalcomponent_set_location(icalcomponent* comp, const char* v)
-{
- ICALSETUPSET(ICAL_LOCATION_PROPERTY)
-
- if (prop == 0){
- prop = icalproperty_new_location(v);
- icalcomponent_add_property(inner, prop);
- }
-
- icalproperty_set_location(prop,v);
-}
-const char* icalcomponent_get_location(icalcomponent* comp)
-{
- icalcomponent *inner;
- icalproperty *prop;
- icalerror_check_arg_rz(comp!=0,"comp");
-
- inner = icalcomponent_get_inner(comp);
-
- if(inner == 0){
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- return 0;
- }
-
- prop= icalcomponent_get_first_property(inner,ICAL_LOCATION_PROPERTY);
-
- if (prop == 0){
- return 0;
- }
-
- return icalproperty_get_location(prop);
-}
-
-void icalcomponent_set_sequence(icalcomponent* comp, int v)
-{
- ICALSETUPSET(ICAL_SEQUENCE_PROPERTY);
-
- if (prop == 0){
- prop = icalproperty_new_sequence(v);
- icalcomponent_add_property(inner, prop);
- }
-
- icalproperty_set_sequence(prop,v);
-
-}
-int icalcomponent_get_sequence(icalcomponent* comp){
- icalcomponent *inner;
- icalproperty *prop;
- icalerror_check_arg_rz(comp!=0,"comp");
-
- inner = icalcomponent_get_inner(comp);
-
- if(inner == 0){
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- return 0;
- }
-
- prop= icalcomponent_get_first_property(inner,ICAL_SEQUENCE_PROPERTY);
-
- if (prop == 0){
- return 0;
- }
-
- return icalproperty_get_sequence(prop);
-}
-
-
-void icalcomponent_set_status(icalcomponent* comp, enum icalproperty_status v)
-{
- ICALSETUPSET(ICAL_STATUS_PROPERTY);
-
- if (prop == 0){
- prop = icalproperty_new_status(v);
- icalcomponent_add_property(inner, prop);
- }
-
- icalproperty_set_status(prop,v);
-
-}
-enum icalproperty_status icalcomponent_get_status(icalcomponent* comp){
- icalcomponent *inner;
- icalproperty *prop;
- icalerror_check_arg_rz(comp!=0,"comp");
-
- inner = icalcomponent_get_inner(comp);
-
- if(inner == 0){
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- return 0;
- }
-
- prop= icalcomponent_get_first_property(inner,ICAL_STATUS_PROPERTY);
-
- if (prop == 0){
- return 0;
- }
-
- return icalproperty_get_status(prop);
-}
-
-icalcomponent* icalcomponent_new_vcalendar()
-{
- return icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
-}
-icalcomponent* icalcomponent_new_vevent()
-{
- return icalcomponent_new(ICAL_VEVENT_COMPONENT);
-}
-icalcomponent* icalcomponent_new_vtodo()
-{
- return icalcomponent_new(ICAL_VTODO_COMPONENT);
-}
-icalcomponent* icalcomponent_new_vjournal()
-{
- return icalcomponent_new(ICAL_VJOURNAL_COMPONENT);
-}
-icalcomponent* icalcomponent_new_valarm()
-{
- return icalcomponent_new(ICAL_VALARM_COMPONENT);
-}
-icalcomponent* icalcomponent_new_vfreebusy()
-{
- return icalcomponent_new(ICAL_VFREEBUSY_COMPONENT);
-}
-icalcomponent* icalcomponent_new_vtimezone()
-{
- return icalcomponent_new(ICAL_VTIMEZONE_COMPONENT);
-}
-icalcomponent* icalcomponent_new_xstandard()
-{
- return icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
-}
-icalcomponent* icalcomponent_new_xdaylight()
-{
- return icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
-}
-icalcomponent* icalcomponent_new_vagenda()
-{
- return icalcomponent_new(ICAL_VAGENDA_COMPONENT);
-}
-icalcomponent* icalcomponent_new_vquery()
-{
- return icalcomponent_new(ICAL_VQUERY_COMPONENT);
-}
-
-/*
- * Timezone stuff.
- */
-
-
-/**
- * This takes 2 VCALENDAR components and merges the second one into the first,
- * resolving any problems with conflicting TZIDs. comp_to_merge will no
- * longer exist after calling this function.
- */
-void icalcomponent_merge_component(icalcomponent* comp,
- icalcomponent* comp_to_merge)
-{
- icalcomponent *subcomp, *next_subcomp;
- icalarray *tzids_to_rename;
- unsigned int i;
-
- /* Check that both components are VCALENDAR components. */
- assert (icalcomponent_isa(comp) == ICAL_VCALENDAR_COMPONENT);
- assert (icalcomponent_isa(comp_to_merge) == ICAL_VCALENDAR_COMPONENT);
-
- /* Step through each subcomponent of comp_to_merge, looking for VTIMEZONEs.
- For each VTIMEZONE found, check if we need to add it to comp and if we
- need to rename it and all TZID references to it. */
- tzids_to_rename = icalarray_new (sizeof (char*), 16);
- subcomp = icalcomponent_get_first_component (comp_to_merge,
- ICAL_VTIMEZONE_COMPONENT);
- while (subcomp) {
- next_subcomp = icalcomponent_get_next_component (comp_to_merge,
- ICAL_VTIMEZONE_COMPONENT);
- /* This will add the VTIMEZONE to comp, if necessary, and also update
- the array of TZIDs we need to rename. */
- icalcomponent_merge_vtimezone (comp, subcomp, tzids_to_rename);
- /* FIXME: Handle possible NEWFAILED error. */
-
- subcomp = next_subcomp;
- }
-
- /* If we need to do any renaming of TZIDs, do it now. */
- if (tzids_to_rename->num_elements != 0) {
- icalcomponent_rename_tzids (comp_to_merge, tzids_to_rename);
-
- /* Now free the tzids_to_rename array. */
- for (i = 0; i < tzids_to_rename->num_elements; i++) {
- free (icalarray_element_at (tzids_to_rename, i));
- }
- icalarray_free (tzids_to_rename);
- }
-
- /* Now move all the components from comp_to_merge to comp, excluding
- VTIMEZONE components. */
- subcomp = icalcomponent_get_first_component (comp_to_merge,
- ICAL_ANY_COMPONENT);
- while (subcomp) {
- next_subcomp = icalcomponent_get_next_component (comp_to_merge,
- ICAL_ANY_COMPONENT);
- if (icalcomponent_isa(subcomp) != ICAL_VTIMEZONE_COMPONENT) {
- icalcomponent_remove_component (comp_to_merge, subcomp);
- icalcomponent_add_component (comp, subcomp);
- }
- subcomp = next_subcomp;
- }
-
- /* Free comp_to_merge. We have moved most of the subcomponents over to
- comp now. */
- icalcomponent_free (comp_to_merge);
-}
-
-
-static void icalcomponent_merge_vtimezone (icalcomponent *comp,
- icalcomponent *vtimezone,
- icalarray *tzids_to_rename)
-{
- icalproperty *tzid_prop;
- const char *tzid;
- char *tzid_copy;
- icaltimezone *existing_vtimezone;
-
- /* Get the TZID of the VTIMEZONE. */
- tzid_prop = icalcomponent_get_first_property (vtimezone, ICAL_TZID_PROPERTY);
- if (!tzid_prop)
- return;
-
- tzid = icalproperty_get_tzid (tzid_prop);
- if (!tzid)
- return;
-
- /* See if there is already a VTIMEZONE in comp with the same TZID. */
- existing_vtimezone = icalcomponent_get_timezone (comp, tzid);
-
- /* If there is no existing VTIMEZONE with the same TZID, we can just move
- the VTIMEZONE to comp and return. */
- if (!existing_vtimezone) {
- icalcomponent_remove_component (icalcomponent_get_parent (vtimezone),
- vtimezone);
- icalcomponent_add_component (comp, vtimezone);
- return;
- }
-
- /* If the TZID has a '/' prefix, then we don't have to worry about the
- clashing TZIDs, as they are supposed to be exactly the same VTIMEZONE. */
- if (tzid[0] == '/')
- return;
-
- /* Now we have two VTIMEZONEs with the same TZID (which isn't a globally
- unique one), so we compare the VTIMEZONE components to see if they are
- the same. If they are, we don't need to do anything. We make a copy of
- the tzid, since the parameter may get modified in these calls. */
- tzid_copy = strdup (tzid);
- if (!tzid_copy) {
- icalerror_set_errno(ICAL_NEWFAILED_ERROR);
- return;
- }
-
- if (!icalcomponent_compare_vtimezones (comp, vtimezone)) {
- /* FIXME: Handle possible NEWFAILED error. */
-
- /* Now we have two different VTIMEZONEs with the same TZID. */
- icalcomponent_handle_conflicting_vtimezones (comp, vtimezone, tzid_prop,
- tzid_copy, tzids_to_rename);
- }
- free (tzid_copy);
-}
-
-
-static void
-icalcomponent_handle_conflicting_vtimezones (icalcomponent *comp,
- icalcomponent *vtimezone,
- icalproperty *tzid_prop,
- const char *tzid,
- icalarray *tzids_to_rename)
-{
- int i, suffix, max_suffix = 0, num_elements;
- unsigned int tzid_len;
- char *tzid_copy, *new_tzid, suffix_buf[32];
- (void)tzid_prop; /* hack to stop unused variable warning */
-
- /* Find the length of the TZID without any trailing digits. */
- tzid_len = icalcomponent_get_tzid_prefix_len (tzid);
-
- /* Step through each of the VTIMEZONEs in comp. We may already have the
- clashing VTIMEZONE in the calendar, but it may have been renamed
- (i.e. a unique number added on the end of the TZID, e.g. 'London2').
- So we compare the new VTIMEZONE with any VTIMEZONEs that have the
- same prefix (e.g. 'London'). If it matches any of those, we have to
- rename the TZIDs to that TZID, else we rename to a new TZID, using
- the biggest numeric suffix found + 1. */
- num_elements = comp->timezones ? comp->timezones->num_elements : 0;
- for (i = 0; i < num_elements; i++) {
- icaltimezone *zone;
- const char *existing_tzid;
- const char *existing_tzid_copy;
- unsigned int existing_tzid_len;
-
- zone = icalarray_element_at (comp->timezones, i);
- existing_tzid = icaltimezone_get_tzid (zone);
-
- /* Find the length of the TZID without any trailing digits. */
- existing_tzid_len = icalcomponent_get_tzid_prefix_len (existing_tzid);
-
- /* Check if we have the same prefix. */
- if (tzid_len == existing_tzid_len
- && !strncmp (tzid, existing_tzid, tzid_len)) {
- /* Compare the VTIMEZONEs. */
- if (icalcomponent_compare_vtimezones (icaltimezone_get_component (zone),
- vtimezone)) {
- /* The VTIMEZONEs match, so we can use the existing VTIMEZONE. But
- we have to rename TZIDs to this TZID. */
- tzid_copy = strdup (tzid);
- existing_tzid_copy = strdup (existing_tzid);
- if (!tzid_copy || !existing_tzid_copy) {
- icalerror_set_errno(ICAL_NEWFAILED_ERROR);
- } else {
- icalarray_append (tzids_to_rename, tzid_copy);
- icalarray_append (tzids_to_rename, existing_tzid_copy);
- }
- return;
- } else {
- /* FIXME: Handle possible NEWFAILED error. */
-
- /* Convert the suffix to an integer and remember the maximum numeric
- suffix found. */
- suffix = atoi (existing_tzid + existing_tzid_len);
- if (max_suffix < suffix)
- max_suffix = suffix;
- }
- }
- }
-
- /* We didn't find a VTIMEZONE that matched, so we have to rename the TZID,
- using the maximum numerical suffix found + 1. */
- tzid_copy = strdup (tzid);
- snprintf (suffix_buf, sizeof(suffix_buf), "%i", max_suffix + 1);
- new_tzid = malloc (tzid_len + strlen (suffix_buf) + 1);
- if (!new_tzid || !tzid_copy) {
- icalerror_set_errno(ICAL_NEWFAILED_ERROR);
- return;
- }
-
- strncpy (new_tzid, tzid, tzid_len);
- strcpy (new_tzid + tzid_len, suffix_buf);
- icalarray_append (tzids_to_rename, tzid_copy);
- icalarray_append (tzids_to_rename, new_tzid);
-}
-
-
-/* Returns the length of the TZID, without any trailing digits. */
-static unsigned int icalcomponent_get_tzid_prefix_len (const char *tzid)
-{
- int len;
- const char *p;
-
- len = strlen (tzid);
- p = tzid + len - 1;
- while (len > 0 && *p >= '0' && *p <= '9') {
- p--;
- len--;
- }
-
- return len;
-}
-
-
-/**
- * Renames all references to the given TZIDs to a new name. rename_table
- * contains pairs of strings - a current TZID, and the new TZID to rename it
- * to.
- */
-static void icalcomponent_rename_tzids(icalcomponent* comp,
- icalarray* rename_table)
-{
- icalcomponent_foreach_tzid (comp, icalcomponent_rename_tzids_callback,
- rename_table);
-}
-
-
-static void icalcomponent_rename_tzids_callback(icalparameter *param, void *data)
-{
- icalarray *rename_table = data;
- const char *tzid;
- int i;
-
- tzid = icalparameter_get_tzid (param);
- if (!tzid)
- return;
-
- /* Step through the rename table to see if the current TZID matches
- any of the ones we want to rename. */
- for (i = 0; (unsigned int)i < rename_table->num_elements - 1; i += 2) {
- if (!strcmp (tzid, icalarray_element_at (rename_table, i))) {
- icalparameter_set_tzid (param, icalarray_element_at (rename_table, i + 1));
- break;
- }
- }
-}
-
-
-/**
- * Calls the given function for each TZID parameter found in the component.
- */
-void icalcomponent_foreach_tzid(icalcomponent* comp,
- void (*callback)(icalparameter *param, void *data),
- void *callback_data)
-{
- icalproperty *prop;
- icalproperty_kind kind;
- icalparameter *param;
- icalcomponent *subcomp;
-
- /* First look for any TZID parameters used in this component itself. */
- prop = icalcomponent_get_first_property (comp, ICAL_ANY_PROPERTY);
- while (prop) {
- kind = icalproperty_isa (prop);
-
- /* These are the only properties that can have a TZID. Note that
- COMPLETED, CREATED, DTSTAMP & LASTMODIFIED must be in UTC. */
- if (kind == ICAL_DTSTART_PROPERTY || kind == ICAL_DTEND_PROPERTY
- || kind == ICAL_DUE_PROPERTY || kind == ICAL_EXDATE_PROPERTY
- || kind == ICAL_RDATE_PROPERTY) {
- param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER);
- if (param)
- (*callback) (param, callback_data);
- }
-
- prop = icalcomponent_get_next_property (comp, ICAL_ANY_PROPERTY);
- }
-
- /* Now recursively check child components. */
- subcomp = icalcomponent_get_first_component (comp, ICAL_ANY_COMPONENT);
- while (subcomp) {
- icalcomponent_foreach_tzid (subcomp, callback, callback_data);
- subcomp = icalcomponent_get_next_component (comp, ICAL_ANY_COMPONENT);
- }
-}
-
-
-
-/**
- * Returns the icaltimezone from the component corresponding to the given
- * TZID, or NULL if the component does not have a corresponding VTIMEZONE.
- */
-icaltimezone* icalcomponent_get_timezone(icalcomponent* comp, const char *tzid)
-{
- icaltimezone *zone;
- int lower, upper, middle, cmp;
- const char *zone_tzid;
-
- if (!comp->timezones)
- return NULL;
-
- /* Sort the array if necessary (by the TZID string). */
- if (!comp->timezones_sorted) {
- icalarray_sort (comp->timezones, icalcomponent_compare_timezone_fn);
- comp->timezones_sorted = 1;
- }
-
- /* Do a simple binary search. */
- lower = middle = 0;
- upper = comp->timezones->num_elements;
-
- while (lower < upper) {
- middle = (lower + upper) >> 1;
- zone = icalarray_element_at (comp->timezones, middle);
- zone_tzid = icaltimezone_get_tzid (zone);
- cmp = strcmp (tzid, zone_tzid);
- if (cmp == 0)
- return zone;
- else if (cmp < 0)
- upper = middle;
- else
- lower = middle + 1;
- }
-
- return NULL;
-}
-
-
-/**
- * A function to compare 2 icaltimezone elements, used for qsort().
- */
-static int icalcomponent_compare_timezone_fn (const void *elem1,
- const void *elem2)
-{
- icaltimezone *zone1, *zone2;
- const char *zone1_tzid, *zone2_tzid;
-
- zone1 = (icaltimezone*) elem1;
- zone2 = (icaltimezone*) elem2;
-
- zone1_tzid = icaltimezone_get_tzid (zone1);
- zone2_tzid = icaltimezone_get_tzid (zone2);
-
- return strcmp (zone1_tzid, zone2_tzid);
-}
-
-
-/**
- * Compares 2 VTIMEZONE components to see if they match, ignoring their TZIDs.
- * It returns 1 if they match, 0 if they don't, or -1 on error.
- */
-static int icalcomponent_compare_vtimezones (icalcomponent *vtimezone1,
- icalcomponent *vtimezone2)
-{
- icalproperty *prop1, *prop2;
- const char *tzid1, *tzid2;
- char *tzid2_copy, *string1, *string2;
- int cmp;
-
- /* Get the TZID property of the first VTIMEZONE. */
- prop1 = icalcomponent_get_first_property (vtimezone1, ICAL_TZID_PROPERTY);
- if (!prop1)
- return -1;
-
- tzid1 = icalproperty_get_tzid (prop1);
- if (!tzid1)
- return -1;
-
- /* Get the TZID property of the second VTIMEZONE. */
- prop2 = icalcomponent_get_first_property (vtimezone2, ICAL_TZID_PROPERTY);
- if (!prop2)
- return -1;
-
- tzid2 = icalproperty_get_tzid (prop2);
- if (!tzid2)
- return -1;
-
- /* Copy the second TZID, and set the property to the same as the first
- TZID, since we don't care if these match of not. */
- tzid2_copy = strdup (tzid2);
- if (!tzid2_copy) {
- icalerror_set_errno (ICAL_NEWFAILED_ERROR);
- return 0;
- }
-
- icalproperty_set_tzid (prop2, tzid1);
-
- /* Now convert both VTIMEZONEs to strings and compare them. */
- string1 = icalcomponent_as_ical_string (vtimezone1);
- if (!string1) {
- free (tzid2_copy);
- return -1;
- }
-
- string2 = icalcomponent_as_ical_string (vtimezone2);
- if (!string2) {
- free (string1);
- free (tzid2_copy);
- return -1;
- }
-
- cmp = strcmp (string1, string2);
-
- free (string1);
- free (string2);
-
- /* Now reset the second TZID. */
- icalproperty_set_tzid (prop2, tzid2_copy);
- free (tzid2_copy);
-
- return (cmp == 0) ? 1 : 0;
-}
-
-
-
-
-
-
-/**
- * @brief set the RELCALID property of a component.
- *
- * @param comp Valid calendar component.
- * @param v Relcalid URL value
- */
-
-void icalcomponent_set_relcalid(icalcomponent* comp, const char* v)
-{
- ICALSETUPSET(ICAL_RELCALID_PROPERTY);
-
- if (prop == 0){
- prop = icalproperty_new_relcalid(v);
- icalcomponent_add_property(inner, prop);
- }
-
- icalproperty_set_relcalid(prop,v);
-
-}
-
-
-/**
- * @brief get the RELCALID property of a component.
- *
- * @param comp Valid calendar component.
- */
-
-const char* icalcomponent_get_relcalid(icalcomponent* comp){
- icalcomponent *inner;
- icalproperty *prop;
- icalerror_check_arg_rz(comp!=0,"comp");
-
- inner = icalcomponent_get_inner(comp);
-
- if(inner == 0){
- return 0;
- }
-
- prop= icalcomponent_get_first_property(inner,ICAL_RELCALID_PROPERTY);
-
- if (prop == 0){
- return 0;
- }
-
- return icalproperty_get_relcalid(prop);
-}
-
-
-/** @brief Return the time a TODO task is DUE.
- *
- * @param comp Valid calendar component.
- *
- * Uses the DUE: property if it exists, otherwise we calculate the DUE
- * value by adding the task's duration to the DTSTART time
- */
-
-struct icaltimetype icalcomponent_get_due(icalcomponent* comp)
-{
- icalcomponent *inner = icalcomponent_get_inner(comp);
-
- icalproperty *due_prop
- = icalcomponent_get_first_property(inner,ICAL_DUE_PROPERTY);
-
- icalproperty *dur_prop
- = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
-
- if( due_prop == 0 && dur_prop == 0){
- return icaltime_null_time();
- } else if ( due_prop != 0) {
- return icalproperty_get_due(due_prop);
- } else if ( dur_prop != 0) {
-
- struct icaltimetype start =
- icalcomponent_get_dtstart(inner);
- struct icaldurationtype duration =
- icalproperty_get_duration(dur_prop);
-
- struct icaltimetype due = icaltime_add(start,duration);
-
- return due;
-
- } else {
- /* Error, both duration and due have been specified */
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- return icaltime_null_time();
-
- }
-
-}
-
-/** @brief Set the due date of a VTODO task.
- *
- * @param comp Valid VTODO component.
- * @param v Valid due date time.
- *
- * - If no duration or due properties then set the DUE property.
- * - If a DUE property is already set, then reset it to the value v.
- * - If a DURATION property is already set, then calculate the new
- * duration based on the supplied value of v.
- */
-
-void icalcomponent_set_due(icalcomponent* comp, struct icaltimetype v)
-{
- icalcomponent *inner = icalcomponent_get_inner(comp);
-
- icalproperty *due_prop
- = icalcomponent_get_first_property(inner,ICAL_DUE_PROPERTY);
-
- icalproperty *dur_prop
- = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
-
-
- if( due_prop == 0 && dur_prop == 0){
- due_prop = icalproperty_new_due(v);
- icalcomponent_add_property(inner,due_prop);
- } else if ( due_prop != 0) {
- icalproperty_set_due(due_prop,v);
- } else if ( dur_prop != 0) {
- struct icaltimetype start =
- icalcomponent_get_dtstart(inner);
-
- struct icaltimetype due =
- icalcomponent_get_due(inner);
-
- struct icaldurationtype dur
- = icaltime_subtract(due,start);
-
- icalproperty_set_duration(dur_prop,dur);
-
- } else {
- /* Error, both duration and due have been specified */
- icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
- }
-}