/*====================================================================== FILE: icalcomponent.c CREATOR: eric 28 April 1999 $Id$ (C) COPYRIGHT 2000, Eric Busboom, 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 /* for malloc */ #include /* for va_list, etc */ #include #include #include /* for fprintf */ #define MAX_TMP 1024 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; }; /* 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(struct icalcomponent_impl *impl,va_list args); icalcomponent* icalcomponent_new_impl (icalcomponent_kind kind); int icalcomponent_property_sorter(void *a, void *b); void icalcomponent_add_children(struct icalcomponent_impl *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((icalcomponent*)impl, (icalcomponent*)vp); } else if (icalproperty_isa_property(vp) != 0 ){ icalcomponent_add_property((icalcomponent*)impl, (icalproperty*)vp); } } } icalcomponent* icalcomponent_new_impl (icalcomponent_kind kind) { struct icalcomponent_impl* comp; if ( ( comp = (struct icalcomponent_impl*) malloc(sizeof(struct icalcomponent_impl))) == 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; return comp; } icalcomponent* icalcomponent_new (icalcomponent_kind kind) { return (icalcomponent*)icalcomponent_new_impl(kind); } icalcomponent* icalcomponent_vanew (icalcomponent_kind kind, ...) { va_list args; struct icalcomponent_impl *impl = icalcomponent_new_impl(kind); if (impl == 0){ return 0; } va_start(args,kind); icalcomponent_add_children(impl, args); va_end(args); return (icalcomponent*) impl; } icalcomponent* icalcomponent_new_from_string(char* str) { icalcomponent_kind kind; icalerror_check_arg_rz( (str!=0), "str"); kind = icalenum_string_to_component_kind(str); if (kind == ICAL_NO_COMPONENT){ return 0; } return icalcomponent_new(kind); } icalcomponent* icalcomponent_new_clone(icalcomponent* component) { struct icalcomponent_impl *old = (struct icalcomponent_impl*)component; struct icalcomponent_impl *new; icalproperty *p; icalcomponent *c; pvl_elem itr; icalerror_check_arg_rv( (component!=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; } void icalcomponent_free (icalcomponent* component) { icalproperty* prop; icalcomponent* comp; struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; icalerror_check_arg_rv( (component!=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(component != 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(component,comp); icalcomponent_free(comp); } pvl_free(c->components); if (c->x_name != 0) { free(c->x_name); } 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'; free(c); } } char* icalcomponent_as_ical_string (icalcomponent* component) { char* buf, *out_buf; char* tmp_buf; size_t buf_size = 1024; char* buf_ptr = 0; pvl_elem itr; struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; #ifdef ICAL_UNIX_NEWLINE char newline[] = "\n"; #else char newline[] = "\r\n"; #endif icalcomponent *c; icalproperty *p; icalcomponent_kind kind = icalcomponent_isa(component); const char* kind_string; buf = icalmemory_new_buffer(buf_size); buf_ptr = buf; icalerror_check_arg_rz( (component!=0), "component"); icalerror_check_arg_rz( (kind!=ICAL_NO_COMPONENT), "component kind is ICAL_NO_COMPONENT"); kind_string = icalenum_component_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, icalenum_component_kind_to_string(kind)); 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) { struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component; if ( (strcmp(impl->id,"comp") == 0) && impl->kind != ICAL_NO_COMPONENT){ return 1; } else { return 0; } } icalcomponent_kind icalcomponent_isa (icalcomponent* component) { struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component; icalerror_check_arg_rz( (component!=0), "component"); if(component != 0) { return impl->kind; } return ICAL_NO_COMPONENT; } int icalcomponent_isa_component (void* component) { struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component; icalerror_check_arg_rz( (component!=0), "component"); if (strcmp(impl->id,"comp") == 0) { return 1; } else { return 0; } } int icalcomponent_property_sorter(void *a, void *b) { icalproperty_kind kinda, kindb; const char *ksa, *ksb; kinda = icalproperty_isa((icalproperty*)a); kindb = icalproperty_isa((icalproperty*)b); ksa = icalenum_property_kind_to_string(kinda); ksb = icalenum_property_kind_to_string(kindb); return strcmp(ksa,ksb); } void icalcomponent_add_property (icalcomponent* component, icalproperty* property) { struct icalcomponent_impl *impl; icalerror_check_arg_rv( (component!=0), "component"); icalerror_check_arg_rv( (property!=0), "property"); impl = (struct icalcomponent_impl*)component; 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); #ifdef ICAL_INSERT_ORDERED pvl_insert_ordered(impl->properties, icalcomponent_property_sorter,property); #else pvl_push(impl->properties,property); #endif } void icalcomponent_remove_property (icalcomponent* component, icalproperty* property) { struct icalcomponent_impl *impl; pvl_elem itr, next_itr; struct icalproperty_impl *pimpl; icalerror_check_arg_rv( (component!=0), "component"); icalerror_check_arg_rv( (property!=0), "property"); impl = (struct icalcomponent_impl*)component; pimpl = (struct icalproperty_impl*)property; icalerror_assert( (icalproperty_get_parent(property)),"The property is not a member of a component"); for( itr = pvl_head(impl->properties); itr != 0; itr = next_itr) { next_itr = pvl_next(itr); if( pvl_data(itr) == (void*)property ){ if (impl->property_iterator == itr){ impl->property_iterator = pvl_next(itr); } pvl_remove( impl->properties, itr); icalproperty_set_parent(property,0); } } } int icalcomponent_count_properties (icalcomponent* component, icalproperty_kind kind) { int count=0; pvl_elem itr; struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; icalerror_check_arg_rz( (component!=0), "component"); for( itr = pvl_head(impl->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) { struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; icalerror_check_arg_rz( (component!=0),"component"); if ((c->property_iterator==0)){ return 0; } return (icalproperty*) pvl_data(c->property_iterator); } icalproperty* icalcomponent_get_first_property (icalcomponent* component, icalproperty_kind kind) { struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; icalerror_check_arg_rz( (component!=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* component, icalproperty_kind kind) { struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; icalerror_check_arg_rz( (component!=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) { struct icalcomponent_impl *impl, *cimpl; icalerror_check_arg_rv( (parent!=0), "parent"); icalerror_check_arg_rv( (child!=0), "child"); impl = (struct icalcomponent_impl*)parent; cimpl = (struct icalcomponent_impl*)child; icalerror_assert( (cimpl->parent ==0),"The child component has already been added to a parent component. Remove the component with icalcomponent_remove_component before calling icalcomponent_add_component"); cimpl->parent = parent; pvl_push(impl->components,child); } void icalcomponent_remove_component (icalcomponent* parent, icalcomponent* child) { struct icalcomponent_impl *impl,*cimpl; pvl_elem itr, next_itr; icalerror_check_arg_rv( (parent!=0), "parent"); icalerror_check_arg_rv( (child!=0), "child"); impl = (struct icalcomponent_impl*)parent; cimpl = (struct icalcomponent_impl*)child; for( itr = pvl_head(impl->components); itr != 0; itr = next_itr) { next_itr = pvl_next(itr); if( pvl_data(itr) == (void*)child ){ if (impl->component_iterator == itr){ /* Don't let the current iterator become invalid */ /* HACK. The semantics for this are troubling. */ impl->component_iterator = pvl_next(impl->component_iterator); } pvl_remove( impl->components, itr); cimpl->parent = 0; break; } } } int icalcomponent_count_components (icalcomponent* component, icalcomponent_kind kind) { int count=0; pvl_elem itr; struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; icalerror_check_arg_rz( (component!=0), "component"); for( itr = pvl_head(impl->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) { struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; icalerror_check_arg_rz( (component!=0),"component"); if (c->component_iterator == 0){ return 0; } return (icalcomponent*) pvl_data(c->component_iterator); } icalcomponent* icalcomponent_get_first_component (icalcomponent* component, icalcomponent_kind kind) { struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; icalerror_check_arg_rz( (component!=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* component, icalcomponent_kind kind) { struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; icalerror_check_arg_rz( (component!=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 ){ return comp; } } return 0; } time_t icalcomponent_convert_time(icalproperty *p) { struct icaltimetype sict; time_t convt; icalproperty *tzp; /* Though it says _dtstart, it will work for dtend too */ sict = icalproperty_get_dtstart(p); tzp = icalproperty_get_first_parameter(p,ICAL_TZID_PARAMETER); if (sict.is_utc == 1 && tzp != 0){ icalerror_warn("icalcomponent_get_span: component has a UTC DTSTART with a timezone specified "); icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); return 0; } if(sict.is_utc == 1){ /* _as_timet will use gmtime() to do the conversion */ convt = icaltime_as_timet(sict); #ifdef TEST_CONVERT_TIME printf("convert time: use as_timet:\n %s\n %s", icalproperty_as_ical_string(p), ctime(&convt)); #endif } else if (sict.is_utc == 0 && tzp == 0 ) { time_t offset; /* _as_timet will use localtime() to do the conversion */ convt = icaltime_as_timet(sict); offset = icaltime_utc_offset(sict,0); convt += offset; #ifdef TEST_CONVERT_TIME printf("convert time: use as_timet and adjust:\n %s\n %s", icalproperty_as_ical_string(p), ctime(&convt)); #endif } else { /* Convert the time to UTC for the named timezone*/ const char* timezone = icalparameter_get_tzid(tzp); convt = icaltime_as_timet(icaltime_as_utc(sict,timezone)); #ifdef TEST_CONVERT_TIME printf("convert time: use _as_utc:\n %s\n %s", icalproperty_as_ical_string(p), ctime(&convt)); #endif } return convt; } struct icaltime_span icalcomponent_get_span(icalcomponent* comp) { icalcomponent *inner; icalproperty *p, *duration; icalcomponent_kind kind; struct icaltime_span span; struct icaltimetype start; span.start = 0; span.end = 0; span.is_busy= 1; /* initial Error checking */ /* icalerror_check_arg_rz( (comp!=0),"comp");*/ 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 */ p = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY); if (p ==0 ) { icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); /*icalerror_warn("icalcomponent_get_span: component has no DTSTART time");*/ return span; } start = icalproperty_get_dtstart(p); icalerror_clear_errno(); span.start = icalcomponent_convert_time(p); #ifdef TEST_CONVERT_TIME printf("convert time:\n %s %s", icalproperty_as_ical_string(p), ctime(&span.start)); #endif if(icalerrno != ICAL_NO_ERROR){ span.start = 0; return span; } /* The end time could be specified as either a DTEND or a DURATION */ p = icalcomponent_get_first_property(inner, ICAL_DTEND_PROPERTY); duration = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY); if (p==0 && duration == 0 && start.is_date != 1) { icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); /*icalerror_warn("icalcomponent_get_span: component has neither DTEND nor DURATION time");*/ span.start = 0; return span; } if (p!=0){ span.end = icalcomponent_convert_time(p); } else if (start.is_date == 1) { /* Duration is all day */ span.end = span.start + 60*60*24; } else { /* Use the duration */ struct icaldurationtype dur; time_t durt; dur = icalproperty_get_duration(duration); durt = icaldurationtype_as_int(dur); span.end = span.start+durt; } return span; } int icalcomponent_count_errors(icalcomponent* component) { int errors = 0; icalproperty *p; icalcomponent *c; pvl_elem itr; struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; for( itr = pvl_head(impl->properties); itr != 0; itr = pvl_next(itr)) { p = (icalproperty*)pvl_data(itr); if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY) { errors++; } } for( itr = pvl_head(impl->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; struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; for( itr = pvl_head(impl->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(impl->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: { } } if (rst.code != ICAL_UNKNOWN_STATUS){ rst.debug = icalproperty_get_xlicerror(p); icalcomponent_add_property(component, icalproperty_new_requeststatus( icalreqstattype_as_string(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) { struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; return c->parent; } void icalcomponent_set_parent(icalcomponent* component, icalcomponent* parent) { struct icalcomponent_impl *c = (struct icalcomponent_impl*)component; c->parent = parent; } icalcompiter icalcompiter_null = {ICAL_NO_COMPONENT,0}; icalcompiter icalcomponent_begin_component(icalcomponent* component,icalcomponent_kind kind) { struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; icalcompiter itr; pvl_elem i; itr.kind = kind; icalerror_check_arg_re( (component!=0),"component",icalcompiter_null); for( i = pvl_head(impl->components); i != 0; i = pvl_next(itr.iter)) { 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) { struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component; icalcompiter itr; pvl_elem i; itr.kind = kind; icalerror_check_arg_re( (component!=0),"component",icalcompiter_null); for( i = pvl_tail(impl->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; } } void icalcomponent_set_dtstart(icalcomponent* comp, struct icaltimetype v) { icalcomponent *inner = icalcomponent_get_inner(comp); icalproperty *prop = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY); if (prop == 0){ prop = icalproperty_new_dtstart(v); icalcomponent_add_property(inner, prop); } icalproperty_set_dtstart(prop,v); } struct icaltimetype icalcomponent_get_dtstart(icalcomponent* comp) { icalcomponent *inner = icalcomponent_get_inner(comp); icalproperty *prop = icalcomponent_get_first_property(inner,ICAL_DTSTART_PROPERTY); if (prop == 0){ return icaltime_null_time(); } return icalproperty_get_dtstart(prop); } 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); if( end_prop == 0 && dur_prop == 0){ return icaltime_null_time(); } else if ( end_prop != 0) { return icalproperty_get_dtend(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); return end; } else { /* Error, both duration and dtend have been specified */ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); return icaltime_null_time(); } } void icalcomponent_set_dtend(icalcomponent* comp, struct icaltimetype v) { 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); if( end_prop == 0 && dur_prop == 0){ end_prop = icalproperty_new_dtend(v); icalcomponent_add_property(inner,end_prop); } else if ( end_prop != 0) { icalproperty_set_dtend(end_prop,v); } else if ( dur_prop != 0) { struct icaltimetype start = icalcomponent_get_dtstart(inner); struct icaltimetype end = icalcomponent_get_dtend(inner); struct icaldurationtype dur = icaltime_subtract(end,start); icalproperty_set_duration(dur_prop,dur); } else { /* Error, both duration and dtend have been specified */ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); } } void icalcomponent_set_duration(icalcomponent* comp, struct icaldurationtype v) { 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); if( end_prop == 0 && dur_prop == 0){ dur_prop = icalproperty_new_duration(v); icalcomponent_add_property(inner, dur_prop); } else if ( end_prop != 0) { struct icaltimetype start = icalcomponent_get_dtstart(inner); struct icaltimetype new_end = icaltime_add(start,v); icalproperty_set_dtend(end_prop,new_end); } else if ( dur_prop != 0) { icalproperty_set_duration(dur_prop,v); } else { /* Error, both duration and dtend have been specified */ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); } } 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 null_duration; memset(&null_duration,0,sizeof(struct icaldurationtype)); if( end_prop == 0 && dur_prop == 0){ return null_duration; } else if ( end_prop != 0) { struct icaltimetype start = icalcomponent_get_dtstart(inner); time_t startt = icaltime_as_timet(start); struct icaltimetype end = icalcomponent_get_dtend(inner); time_t endt = icaltime_as_timet(end); return icaldurationtype_from_int(endt-startt); } else if ( dur_prop != 0) { return icalproperty_get_duration(dur_prop); } else { /* Error, both duration and dtend have been specified */ icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR); return null_duration; } } 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); } 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); } void icalcomponent_set_dtstamp(icalcomponent* comp, struct icaltimetype v) { icalcomponent *inner = icalcomponent_get_inner(comp); icalproperty *prop = icalcomponent_get_first_property(inner, 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) { icalcomponent *inner = icalcomponent_get_inner(comp); icalproperty *prop = icalcomponent_get_first_property(inner, 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 = icalcomponent_get_inner(comp); icalproperty *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); const char* icalcomponent_get_comment(icalcomponent* comp); void icalcomponent_set_organizer(icalcomponent* comp, const char* v); const char* icalcomponent_get_organizer(icalcomponent* comp); void icalcomponent_set_uid(icalcomponent* comp, const char* v); const char* icalcomponent_get_uid(icalcomponent* comp); void icalcomponent_set_recurrenceid(icalcomponent* comp, struct icaltimetype v); struct icaltimetype icalcomponent_get_recurrenceid(icalcomponent* comp); 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_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); }