1 /*======================================================================
3 CREATOR: eric 28 April 1999
8 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of either:
13 The LGPL as published by the Free Software Foundation, version
14 2.1, available at: http://www.fsf.org/copyleft/lesser.html
18 The Mozilla Public License Version 1.0. You may obtain a copy of
19 the License at http://www.mozilla.org/MPL/
21 The original code is icalcomponent.c
23 ======================================================================*/
30 #include "icalcomponent.h"
31 #include "pvl.h" /* "Pointer-to-void list" */
32 #include "icalerror.h"
33 #include "icalmemory.h"
34 #include "icalenums.h"
36 #include "icalduration.h"
37 #include "icalperiod.h"
38 #include "icalparser.h"
40 #include <string.h> /* for strcpy & memset */
41 #include <stdlib.h> /* for malloc */
42 #include <stdarg.h> /* for va_list, etc */
45 #include <stdio.h> /* for fprintf */
49 struct icalcomponent_impl
52 icalcomponent_kind kind;
55 pvl_elem property_iterator;
57 pvl_elem component_iterator;
58 icalcomponent* parent;
61 /* icalproperty functions that only components get to use */
62 void icalproperty_set_parent(icalproperty* property,
63 icalcomponent* component);
64 icalcomponent* icalproperty_get_parent(icalproperty* property);
65 void icalcomponent_add_children(struct icalcomponent_impl *impl,va_list args);
66 icalcomponent* icalcomponent_new_impl (icalcomponent_kind kind);
67 int icalcomponent_property_sorter(void *a, void *b);
70 void icalcomponent_add_children(struct icalcomponent_impl *impl,va_list args)
74 while((vp = va_arg(args, void*)) != 0) {
76 assert (icalcomponent_isa_component(vp) != 0 ||
77 icalproperty_isa_property(vp) != 0 ) ;
79 if (icalcomponent_isa_component(vp) != 0 ){
81 icalcomponent_add_component((icalcomponent*)impl,
84 } else if (icalproperty_isa_property(vp) != 0 ){
86 icalcomponent_add_property((icalcomponent*)impl,
93 icalcomponent_new_impl (icalcomponent_kind kind)
95 struct icalcomponent_impl* comp;
97 if ( ( comp = (struct icalcomponent_impl*)
98 malloc(sizeof(struct icalcomponent_impl))) == 0) {
99 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
103 strcpy(comp->id,"comp");
106 comp->properties = pvl_newlist();
107 comp->property_iterator = 0;
108 comp->components = pvl_newlist();
109 comp->component_iterator = 0;
117 icalcomponent_new (icalcomponent_kind kind)
119 return (icalcomponent*)icalcomponent_new_impl(kind);
123 icalcomponent_vanew (icalcomponent_kind kind, ...)
127 struct icalcomponent_impl *impl = icalcomponent_new_impl(kind);
134 icalcomponent_add_children(impl, args);
137 return (icalcomponent*) impl;
140 icalcomponent* icalcomponent_new_from_string(char* str)
142 return icalparser_parse_string(str);
145 icalcomponent* icalcomponent_new_clone(icalcomponent* component)
147 struct icalcomponent_impl *old = (struct icalcomponent_impl*)component;
148 struct icalcomponent_impl *new;
153 icalerror_check_arg_rz( (component!=0), "component");
155 new = icalcomponent_new_impl(old->kind);
162 for( itr = pvl_head(old->properties);
166 p = (icalproperty*)pvl_data(itr);
167 icalcomponent_add_property(new,icalproperty_new_clone(p));
171 for( itr = pvl_head(old->components);
175 c = (icalcomponent*)pvl_data(itr);
176 icalcomponent_add_component(new,icalcomponent_new_clone(c));
185 icalcomponent_free (icalcomponent* component)
189 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
191 icalerror_check_arg_rv( (component!=0), "component");
193 #ifdef ICAL_FREE_ON_LIST_IS_ERROR
194 icalerror_assert( (c->parent ==0),"Tried to free a component that is still attached to a parent component");
203 while( (prop=pvl_pop(c->properties)) != 0){
205 icalproperty_set_parent(prop,0);
206 icalproperty_free(prop);
209 pvl_free(c->properties);
211 while( (comp=pvl_data(pvl_head(c->components))) != 0){
213 icalcomponent_remove_component(component,comp);
214 icalcomponent_free(comp);
217 pvl_free(c->components);
219 if (c->x_name != 0) {
223 c->kind = ICAL_NO_COMPONENT;
225 c->property_iterator = 0;
227 c->component_iterator = 0;
236 icalcomponent_as_ical_string (icalcomponent* component)
240 size_t buf_size = 1024;
243 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
245 #ifdef ICAL_UNIX_NEWLINE
246 char newline[] = "\n";
248 char newline[] = "\r\n";
253 icalcomponent_kind kind = icalcomponent_isa(component);
255 const char* kind_string;
257 buf = icalmemory_new_buffer(buf_size);
260 icalerror_check_arg_rz( (component!=0), "component");
261 icalerror_check_arg_rz( (kind!=ICAL_NO_COMPONENT), "component kind is ICAL_NO_COMPONENT");
263 kind_string = icalenum_component_kind_to_string(kind);
265 icalerror_check_arg_rz( (kind_string!=0),"Unknown kind of component");
267 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "BEGIN:");
268 icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
269 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
273 for( itr = pvl_head(impl->properties);
277 p = (icalproperty*)pvl_data(itr);
279 icalerror_assert((p!=0),"Got a null property");
280 tmp_buf = icalproperty_as_ical_string(p);
282 icalmemory_append_string(&buf, &buf_ptr, &buf_size, tmp_buf);
286 for( itr = pvl_head(impl->components);
290 c = (icalcomponent*)pvl_data(itr);
292 tmp_buf = icalcomponent_as_ical_string(c);
294 icalmemory_append_string(&buf, &buf_ptr, &buf_size, tmp_buf);
298 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "END:");
299 icalmemory_append_string(&buf, &buf_ptr, &buf_size,
300 icalenum_component_kind_to_string(kind));
301 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
303 out_buf = icalmemory_tmp_copy(buf);
311 icalcomponent_is_valid (icalcomponent* component)
313 struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component;
316 if ( (strcmp(impl->id,"comp") == 0) &&
317 impl->kind != ICAL_NO_COMPONENT){
327 icalcomponent_isa (icalcomponent* component)
329 struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component;
330 icalerror_check_arg_rz( (component!=0), "component");
337 return ICAL_NO_COMPONENT;
342 icalcomponent_isa_component (void* component)
344 struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component;
346 icalerror_check_arg_rz( (component!=0), "component");
348 if (strcmp(impl->id,"comp") == 0) {
356 int icalcomponent_property_sorter(void *a, void *b)
358 icalproperty_kind kinda, kindb;
359 const char *ksa, *ksb;
361 kinda = icalproperty_isa((icalproperty*)a);
362 kindb = icalproperty_isa((icalproperty*)b);
364 ksa = icalenum_property_kind_to_string(kinda);
365 ksb = icalenum_property_kind_to_string(kindb);
367 return strcmp(ksa,ksb);
372 icalcomponent_add_property (icalcomponent* component, icalproperty* property)
374 struct icalcomponent_impl *impl;
376 icalerror_check_arg_rv( (component!=0), "component");
377 icalerror_check_arg_rv( (property!=0), "property");
379 impl = (struct icalcomponent_impl*)component;
381 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");
383 icalproperty_set_parent(property,component);
385 #ifdef ICAL_INSERT_ORDERED
386 pvl_insert_ordered(impl->properties,
387 icalcomponent_property_sorter,property);
389 pvl_push(impl->properties,property);
396 icalcomponent_remove_property (icalcomponent* component, icalproperty* property)
398 struct icalcomponent_impl *impl;
399 pvl_elem itr, next_itr;
401 icalerror_check_arg_rv( (component!=0), "component");
402 icalerror_check_arg_rv( (property!=0), "property");
404 impl = (struct icalcomponent_impl*)component;
406 icalerror_assert( (icalproperty_get_parent(property)),"The property is not a member of a component");
409 for( itr = pvl_head(impl->properties);
413 next_itr = pvl_next(itr);
415 if( pvl_data(itr) == (void*)property ){
417 if (impl->property_iterator == itr){
418 impl->property_iterator = pvl_next(itr);
421 pvl_remove( impl->properties, itr);
422 icalproperty_set_parent(property,0);
428 icalcomponent_count_properties (icalcomponent* component,
429 icalproperty_kind kind)
433 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
435 icalerror_check_arg_rz( (component!=0), "component");
437 for( itr = pvl_head(impl->properties);
441 if(kind == icalproperty_isa((icalproperty*)pvl_data(itr)) ||
442 kind == ICAL_ANY_PROPERTY){
452 icalproperty* icalcomponent_get_current_property (icalcomponent* component)
455 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
456 icalerror_check_arg_rz( (component!=0),"component");
458 if ((c->property_iterator==0)){
462 return (icalproperty*) pvl_data(c->property_iterator);
467 icalcomponent_get_first_property (icalcomponent* component, icalproperty_kind kind)
469 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
470 icalerror_check_arg_rz( (component!=0),"component");
472 for( c->property_iterator = pvl_head(c->properties);
473 c->property_iterator != 0;
474 c->property_iterator = pvl_next(c->property_iterator)) {
476 icalproperty *p = (icalproperty*) pvl_data(c->property_iterator);
478 if (icalproperty_isa(p) == kind || kind == ICAL_ANY_PROPERTY) {
487 icalcomponent_get_next_property (icalcomponent* component, icalproperty_kind kind)
489 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
490 icalerror_check_arg_rz( (component!=0),"component");
492 if (c->property_iterator == 0){
496 for( c->property_iterator = pvl_next(c->property_iterator);
497 c->property_iterator != 0;
498 c->property_iterator = pvl_next(c->property_iterator)) {
500 icalproperty *p = (icalproperty*) pvl_data(c->property_iterator);
502 if (icalproperty_isa(p) == kind || kind == ICAL_ANY_PROPERTY) {
513 icalcomponent_get_properties (icalcomponent* component, icalproperty_kind kind);
517 icalcomponent_add_component (icalcomponent* parent, icalcomponent* child)
519 struct icalcomponent_impl *impl, *cimpl;
521 icalerror_check_arg_rv( (parent!=0), "parent");
522 icalerror_check_arg_rv( (child!=0), "child");
524 impl = (struct icalcomponent_impl*)parent;
525 cimpl = (struct icalcomponent_impl*)child;
527 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");
529 cimpl->parent = parent;
531 pvl_push(impl->components,child);
536 icalcomponent_remove_component (icalcomponent* parent, icalcomponent* child)
538 struct icalcomponent_impl *impl,*cimpl;
539 pvl_elem itr, next_itr;
541 icalerror_check_arg_rv( (parent!=0), "parent");
542 icalerror_check_arg_rv( (child!=0), "child");
544 impl = (struct icalcomponent_impl*)parent;
545 cimpl = (struct icalcomponent_impl*)child;
547 for( itr = pvl_head(impl->components);
551 next_itr = pvl_next(itr);
553 if( pvl_data(itr) == (void*)child ){
555 if (impl->component_iterator == itr){
556 /* Don't let the current iterator become invalid */
558 /* HACK. The semantics for this are troubling. */
559 impl->component_iterator =
560 pvl_next(impl->component_iterator);
563 pvl_remove( impl->components, itr);
572 icalcomponent_count_components (icalcomponent* component,
573 icalcomponent_kind kind)
577 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
579 icalerror_check_arg_rz( (component!=0), "component");
581 for( itr = pvl_head(impl->components);
585 if(kind == icalcomponent_isa((icalcomponent*)pvl_data(itr)) ||
586 kind == ICAL_ANY_COMPONENT){
595 icalcomponent_get_current_component(icalcomponent* component)
597 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
599 icalerror_check_arg_rz( (component!=0),"component");
601 if (c->component_iterator == 0){
605 return (icalcomponent*) pvl_data(c->component_iterator);
609 icalcomponent_get_first_component (icalcomponent* component,
610 icalcomponent_kind kind)
612 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
614 icalerror_check_arg_rz( (component!=0),"component");
616 for( c->component_iterator = pvl_head(c->components);
617 c->component_iterator != 0;
618 c->component_iterator = pvl_next(c->component_iterator)) {
620 icalcomponent *p = (icalcomponent*) pvl_data(c->component_iterator);
622 if (icalcomponent_isa(p) == kind || kind == ICAL_ANY_COMPONENT) {
633 icalcomponent_get_next_component (icalcomponent* component, icalcomponent_kind kind)
635 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
637 icalerror_check_arg_rz( (component!=0),"component");
639 if (c->component_iterator == 0){
643 for( c->component_iterator = pvl_next(c->component_iterator);
644 c->component_iterator != 0;
645 c->component_iterator = pvl_next(c->component_iterator)) {
647 icalcomponent *p = (icalcomponent*) pvl_data(c->component_iterator);
649 if (icalcomponent_isa(p) == kind || kind == ICAL_ANY_COMPONENT) {
658 icalcomponent* icalcomponent_get_first_real_component(icalcomponent *c)
662 for(comp = icalcomponent_get_first_component(c,ICAL_ANY_COMPONENT);
664 comp = icalcomponent_get_next_component(c,ICAL_ANY_COMPONENT)){
666 icalcomponent_kind kind = icalcomponent_isa(comp);
668 if(kind == ICAL_VEVENT_COMPONENT ||
669 kind == ICAL_VTODO_COMPONENT ||
670 kind == ICAL_VJOURNAL_COMPONENT ){
677 time_t icalcomponent_convert_time(icalproperty *p)
679 struct icaltimetype sict;
684 /* Though it says _dtstart, it will work for dtend too */
685 sict = icalproperty_get_dtstart(p);
687 tzp = icalproperty_get_first_parameter(p,ICAL_TZID_PARAMETER);
689 if (sict.is_utc == 1 && tzp != 0){
690 icalerror_warn("icalcomponent_get_span: component has a UTC DTSTART with a timezone specified ");
691 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
695 if(sict.is_utc == 1){
696 #ifdef TEST_CONVERT_TIME
699 /* _as_timet will use gmtime() to do the conversion */
700 convt = icaltime_as_timet(sict);
702 #ifdef TEST_CONVERT_TIME
703 printf("convert time: use as_timet:\n %s\n %s",
704 icalproperty_as_ical_string(p), ctime_r(&convt,buft));
707 } else if (sict.is_utc == 0 && tzp == 0 ) {
709 #ifdef TEST_CONVERT_TIME
713 /* _as_timet will use localtime() to do the conversion */
714 convt = icaltime_as_timet(sict);
715 offset = icaltime_utc_offset(sict,0);
718 #ifdef TEST_CONVERT_TIME
719 printf("convert time: use as_timet and adjust:\n %s\n %s",
720 icalproperty_as_ical_string(p), ctime_r(&convt,buft));
723 #ifdef TEST_CONVERT_TIME
726 /* Convert the time to UTC for the named timezone*/
727 const char* timezone = icalparameter_get_tzid(tzp);
728 convt = icaltime_as_timet(icaltime_as_utc(sict,timezone));
730 #ifdef TEST_CONVERT_TIME
731 printf("convert time: use _as_utc:\n %s\n %s",
732 icalproperty_as_ical_string(p), ctime_r(&convt,buft));
738 struct icaltime_span icalcomponent_get_span(icalcomponent* comp)
740 icalcomponent *inner;
741 icalproperty *p, *duration;
742 icalcomponent_kind kind;
743 struct icaltime_span span;
744 struct icaltimetype start;
745 #ifdef TEST_CONVERT_TIME
753 /* initial Error checking */
755 /* icalerror_check_arg_rz( (comp!=0),"comp");*/
757 kind = icalcomponent_isa(comp);
759 if(kind == ICAL_VCALENDAR_COMPONENT){
760 inner = icalcomponent_get_first_real_component(comp);
762 /* Maybe there is a VTIMEZONE in there */
764 inner = icalcomponent_get_first_component(comp,
765 ICAL_VTIMEZONE_COMPONENT);
773 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
774 /*icalerror_warn("icalcomponent_get_span: no component specified, or empty VCALENDAR component");*/
778 kind = icalcomponent_isa(inner);
780 if( !( kind == ICAL_VEVENT_COMPONENT ||
781 kind == ICAL_VJOURNAL_COMPONENT ||
782 kind == ICAL_VTODO_COMPONENT ||
783 kind == ICAL_VFREEBUSY_COMPONENT )) {
784 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
785 /*icalerror_warn("icalcomponent_get_span: no component specified, or empty VCALENDAR component");*/
792 /* Get to work. starting with DTSTART */
794 p = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY);
797 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
798 /*icalerror_warn("icalcomponent_get_span: component has no DTSTART time");*/
803 start = icalproperty_get_dtstart(p);
805 icalerror_clear_errno();
807 span.start = icalcomponent_convert_time(p);
809 #ifdef TEST_CONVERT_TIME
810 printf("convert time:\n %s %s",
811 icalproperty_as_ical_string(p), ctime_r(&span.start, buft));
814 if(icalerrno != ICAL_NO_ERROR){
819 /* The end time could be specified as either a DTEND or a DURATION */
820 p = icalcomponent_get_first_property(inner, ICAL_DTEND_PROPERTY);
821 duration = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
823 if (p==0 && duration == 0 && start.is_date != 1) {
824 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
825 /*icalerror_warn("icalcomponent_get_span: component has neither DTEND nor DURATION time");*/
831 span.end = icalcomponent_convert_time(p);
832 } else if (start.is_date == 1) {
833 /* Duration is all day */
834 span.end = span.start + 60*60*24;
836 /* Use the duration */
837 struct icaldurationtype dur;
841 dur = icalproperty_get_duration(duration);
843 durt = icaldurationtype_as_int(dur);
844 span.end = span.start+durt;
852 int icalcomponent_count_errors(icalcomponent* component)
858 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
860 for( itr = pvl_head(impl->properties);
864 p = (icalproperty*)pvl_data(itr);
866 if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
873 for( itr = pvl_head(impl->components);
877 c = (icalcomponent*)pvl_data(itr);
879 errors += icalcomponent_count_errors(c);
887 void icalcomponent_strip_errors(icalcomponent* component)
891 pvl_elem itr, next_itr;
892 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
894 for( itr = pvl_head(impl->properties);
898 p = (icalproperty*)pvl_data(itr);
899 next_itr = pvl_next(itr);
901 if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
903 icalcomponent_remove_property(component,p);
907 for( itr = pvl_head(impl->components);
911 c = (icalcomponent*)pvl_data(itr);
912 icalcomponent_strip_errors(c);
916 /* Hack. This will change the state of the iterators */
917 void icalcomponent_convert_errors(icalcomponent* component)
919 icalproperty *p, *next_p;
922 for(p = icalcomponent_get_first_property(component,ICAL_ANY_PROPERTY);
926 next_p = icalcomponent_get_next_property(component,ICAL_ANY_PROPERTY);
928 if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
930 struct icalreqstattype rst;
931 icalparameter *param = icalproperty_get_first_parameter
932 (p,ICAL_XLICERRORTYPE_PARAMETER);
934 rst.code = ICAL_UNKNOWN_STATUS;
937 switch(icalparameter_get_xlicerrortype(param)){
939 case ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR: {
940 rst.code = ICAL_3_2_INVPARAM_STATUS;
943 case ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR: {
944 rst.code = ICAL_3_3_INVPARAMVAL_STATUS;
947 case ICAL_XLICERRORTYPE_PROPERTYPARSEERROR: {
948 rst.code = ICAL_3_0_INVPROPNAME_STATUS;
951 case ICAL_XLICERRORTYPE_VALUEPARSEERROR: {
952 rst.code = ICAL_3_1_INVPROPVAL_STATUS;
955 case ICAL_XLICERRORTYPE_COMPONENTPARSEERROR: {
956 rst.code = ICAL_3_4_INVCOMP_STATUS;
963 if (rst.code != ICAL_UNKNOWN_STATUS){
965 rst.debug = icalproperty_get_xlicerror(p);
966 icalcomponent_add_property(component,
967 icalproperty_new_requeststatus(
968 icalreqstattype_as_string(rst)
972 icalcomponent_remove_property(component,p);
977 for(c = icalcomponent_get_first_component(component,ICAL_ANY_COMPONENT);
979 c = icalcomponent_get_next_component(component,ICAL_ANY_COMPONENT)){
981 icalcomponent_convert_errors(c);
986 icalcomponent* icalcomponent_get_parent(icalcomponent* component)
988 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
993 void icalcomponent_set_parent(icalcomponent* component, icalcomponent* parent)
995 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
1000 icalcompiter icalcompiter_null = {ICAL_NO_COMPONENT,0};
1003 struct icalcomponent_kind_map {
1004 icalcomponent_kind kind;
1010 static struct icalcomponent_kind_map component_map[] =
1012 { ICAL_VEVENT_COMPONENT, "VEVENT" },
1013 { ICAL_VTODO_COMPONENT, "VTODO" },
1014 { ICAL_VJOURNAL_COMPONENT, "VJOURNAL" },
1015 { ICAL_VCALENDAR_COMPONENT, "VCALENDAR" },
1016 { ICAL_VFREEBUSY_COMPONENT, "VFREEBUSY" },
1017 { ICAL_VTIMEZONE_COMPONENT, "VTIMEZONE" },
1018 { ICAL_VALARM_COMPONENT, "VALARM" },
1019 { ICAL_XSTANDARD_COMPONENT, "STANDARD" }, /*These are part of RFC2445 */
1020 { ICAL_XDAYLIGHT_COMPONENT, "DAYLIGHT" }, /*but are not really components*/
1021 { ICAL_X_COMPONENT, "X" },
1022 { ICAL_VSCHEDULE_COMPONENT, "SCHEDULE" },
1024 /* CAP components */
1025 { ICAL_VQUERY_COMPONENT, "VQUERY" },
1026 { ICAL_VCAR_COMPONENT, "VCAR" },
1027 { ICAL_VCOMMAND_COMPONENT, "VCOMMAND" },
1029 /* libical private components */
1030 { ICAL_XLICINVALID_COMPONENT, "X-LIC-UNKNOWN" },
1031 { ICAL_XLICMIMEPART_COMPONENT, "X-LIC-MIME-PART" },
1032 { ICAL_ANY_COMPONENT, "ANY" },
1033 { ICAL_XROOT_COMPONENT, "XROOT" },
1036 { ICAL_NO_COMPONENT, "" },
1041 const char* icalcomponent_kind_to_string(icalcomponent_kind kind)
1045 for (i=0; component_map[i].kind != ICAL_NO_COMPONENT; i++) {
1046 if (component_map[i].kind == kind) {
1047 return component_map[i].name;
1055 icalcomponent_kind icalcomponent_string_to_kind(const char* string)
1060 return ICAL_NO_COMPONENT;
1063 for (i=0; component_map[i].kind != ICAL_NO_COMPONENT; i++) {
1064 if (strcmp(component_map[i].name, string) == 0) {
1065 return component_map[i].kind;
1069 return ICAL_NO_COMPONENT;
1075 icalcomponent_begin_component(icalcomponent* component,icalcomponent_kind kind)
1077 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
1083 icalerror_check_arg_re( (component!=0),"component",icalcompiter_null);
1085 for( i = pvl_head(impl->components); i != 0; i = pvl_next(i)) {
1087 icalcomponent *c = (icalcomponent*) pvl_data(i);
1089 if (icalcomponent_isa(c) == kind || kind == ICAL_ANY_COMPONENT) {
1097 return icalcompiter_null;
1101 icalcomponent_end_component(icalcomponent* component,icalcomponent_kind kind)
1103 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
1109 icalerror_check_arg_re( (component!=0),"component",icalcompiter_null);
1111 for( i = pvl_tail(impl->components); i != 0; i = pvl_prior(i)) {
1113 icalcomponent *c = (icalcomponent*) pvl_data(i);
1115 if (icalcomponent_isa(c) == kind || kind == ICAL_ANY_COMPONENT) {
1117 itr.iter = pvl_next(i);
1123 return icalcompiter_null;;
1127 icalcomponent* icalcompiter_next(icalcompiter* i)
1133 icalerror_check_arg_rz( (i!=0),"i");
1135 for( i->iter = pvl_next(i->iter);
1137 i->iter = pvl_next(i->iter)) {
1139 icalcomponent *c = (icalcomponent*) pvl_data(i->iter);
1141 if (icalcomponent_isa(c) == i->kind
1142 || i->kind == ICAL_ANY_COMPONENT) {
1144 return icalcompiter_deref(i);;
1152 icalcomponent* icalcompiter_prior(icalcompiter* i)
1158 for( i->iter = pvl_prior(i->iter);
1160 i->iter = pvl_prior(i->iter)) {
1162 icalcomponent *c = (icalcomponent*) pvl_data(i->iter);
1164 if (icalcomponent_isa(c) == i->kind
1165 || i->kind == ICAL_ANY_COMPONENT) {
1167 return icalcompiter_deref(i);;
1174 icalcomponent* icalcompiter_deref(icalcompiter* i)
1180 return pvl_data(i->iter);
1183 icalcomponent* icalcomponent_get_inner(icalcomponent* comp)
1185 if (icalcomponent_isa(comp) == ICAL_VCALENDAR_COMPONENT){
1186 return icalcomponent_get_first_real_component(comp);
1193 void icalcomponent_set_dtstart(icalcomponent* comp, struct icaltimetype v)
1196 icalcomponent *inner = icalcomponent_get_inner(comp);
1198 = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY);
1202 prop = icalproperty_new_dtstart(v);
1203 icalcomponent_add_property(inner, prop);
1206 icalproperty_set_dtstart(prop,v);
1211 struct icaltimetype icalcomponent_get_dtstart(icalcomponent* comp)
1213 icalcomponent *inner = icalcomponent_get_inner(comp);
1215 = icalcomponent_get_first_property(inner,ICAL_DTSTART_PROPERTY);
1218 return icaltime_null_time();
1221 return icalproperty_get_dtstart(prop);
1225 struct icaltimetype icalcomponent_get_dtend(icalcomponent* comp)
1227 icalcomponent *inner = icalcomponent_get_inner(comp);
1229 icalproperty *end_prop
1230 = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
1232 icalproperty *dur_prop
1233 = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
1236 if( end_prop == 0 && dur_prop == 0){
1237 return icaltime_null_time();
1238 } else if ( end_prop != 0) {
1239 return icalproperty_get_dtend(end_prop);
1240 } else if ( dur_prop != 0) {
1242 struct icaltimetype start =
1243 icalcomponent_get_dtstart(inner);
1244 struct icaldurationtype duration =
1245 icalproperty_get_duration(dur_prop);
1247 struct icaltimetype end = icaltime_add(start,duration);
1252 /* Error, both duration and dtend have been specified */
1253 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1254 return icaltime_null_time();
1261 void icalcomponent_set_dtend(icalcomponent* comp, struct icaltimetype v)
1263 icalcomponent *inner = icalcomponent_get_inner(comp);
1265 icalproperty *end_prop
1266 = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
1268 icalproperty *dur_prop
1269 = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
1272 if( end_prop == 0 && dur_prop == 0){
1273 end_prop = icalproperty_new_dtend(v);
1274 icalcomponent_add_property(inner,end_prop);
1275 } else if ( end_prop != 0) {
1276 icalproperty_set_dtend(end_prop,v);
1277 } else if ( dur_prop != 0) {
1278 struct icaltimetype start =
1279 icalcomponent_get_dtstart(inner);
1281 struct icaltimetype end =
1282 icalcomponent_get_dtend(inner);
1284 struct icaldurationtype dur
1285 = icaltime_subtract(end,start);
1287 icalproperty_set_duration(dur_prop,dur);
1290 /* Error, both duration and dtend have been specified */
1291 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1295 void icalcomponent_set_duration(icalcomponent* comp,
1296 struct icaldurationtype v)
1298 icalcomponent *inner = icalcomponent_get_inner(comp);
1300 icalproperty *end_prop
1301 = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
1303 icalproperty *dur_prop
1304 = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
1307 if( end_prop == 0 && dur_prop == 0){
1308 dur_prop = icalproperty_new_duration(v);
1309 icalcomponent_add_property(inner, dur_prop);
1310 } else if ( end_prop != 0) {
1311 struct icaltimetype start =
1312 icalcomponent_get_dtstart(inner);
1314 struct icaltimetype new_end = icaltime_add(start,v);
1316 icalproperty_set_dtend(end_prop,new_end);
1318 } else if ( dur_prop != 0) {
1319 icalproperty_set_duration(dur_prop,v);
1321 /* Error, both duration and dtend have been specified */
1322 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1326 struct icaldurationtype icalcomponent_get_duration(icalcomponent* comp)
1328 icalcomponent *inner = icalcomponent_get_inner(comp);
1330 icalproperty *end_prop
1331 = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
1333 icalproperty *dur_prop
1334 = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
1336 struct icaldurationtype null_duration;
1337 memset(&null_duration,0,sizeof(struct icaldurationtype));
1340 if( end_prop == 0 && dur_prop == 0){
1341 return null_duration;
1342 } else if ( end_prop != 0) {
1343 struct icaltimetype start =
1344 icalcomponent_get_dtstart(inner);
1345 time_t startt = icaltime_as_timet(start);
1347 struct icaltimetype end =
1348 icalcomponent_get_dtend(inner);
1349 time_t endt = icaltime_as_timet(end);
1351 return icaldurationtype_from_int(endt-startt);
1352 } else if ( dur_prop != 0) {
1353 return icalproperty_get_duration(dur_prop);
1355 /* Error, both duration and dtend have been specified */
1356 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1357 return null_duration;
1361 void icalcomponent_set_method(icalcomponent* comp, icalproperty_method method)
1364 = icalcomponent_get_first_property(comp, ICAL_METHOD_PROPERTY);
1368 prop = icalproperty_new_method(method);
1369 icalcomponent_add_property(comp, prop);
1372 icalproperty_set_method(prop,method);
1376 icalproperty_method icalcomponent_get_method(icalcomponent* comp)
1379 = icalcomponent_get_first_property(comp,ICAL_METHOD_PROPERTY);
1382 return ICAL_METHOD_NONE;
1385 return icalproperty_get_method(prop);
1388 void icalcomponent_set_dtstamp(icalcomponent* comp, struct icaltimetype v)
1391 icalcomponent *inner = icalcomponent_get_inner(comp);
1393 = icalcomponent_get_first_property(inner, ICAL_DTSTAMP_PROPERTY);
1397 prop = icalproperty_new_dtstamp(v);
1398 icalcomponent_add_property(inner, prop);
1401 icalproperty_set_dtstamp(prop,v);
1406 struct icaltimetype icalcomponent_get_dtstamp(icalcomponent* comp)
1408 icalcomponent *inner = icalcomponent_get_inner(comp);
1410 = icalcomponent_get_first_property(inner,ICAL_DTSTAMP_PROPERTY);
1413 return icaltime_null_time();
1416 return icalproperty_get_dtstamp(prop);
1420 void icalcomponent_set_summary(icalcomponent* comp, const char* v)
1422 icalcomponent *inner = icalcomponent_get_inner(comp);
1424 = icalcomponent_get_first_property(inner, ICAL_SUMMARY_PROPERTY);
1427 prop = icalproperty_new_summary(v);
1428 icalcomponent_add_property(inner, prop);
1431 icalproperty_set_summary(prop,v);
1435 const char* icalcomponent_get_summary(icalcomponent* comp)
1437 icalcomponent *inner = icalcomponent_get_inner(comp);
1439 = icalcomponent_get_first_property(inner,ICAL_SUMMARY_PROPERTY);
1445 return icalproperty_get_summary(prop);
1449 void icalcomponent_set_comment(icalcomponent* comp, const char* v);
1450 const char* icalcomponent_get_comment(icalcomponent* comp);
1452 void icalcomponent_set_uid(icalcomponent* comp, const char* v);
1453 const char* icalcomponent_get_uid(icalcomponent* comp);
1455 void icalcomponent_set_recurrenceid(icalcomponent* comp,
1456 struct icaltimetype v);
1457 struct icaltimetype icalcomponent_get_recurrenceid(icalcomponent* comp);
1462 icalcomponent* icalcomponent_new_vcalendar()
1464 return icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
1466 icalcomponent* icalcomponent_new_vevent()
1468 return icalcomponent_new(ICAL_VEVENT_COMPONENT);
1470 icalcomponent* icalcomponent_new_vtodo()
1472 return icalcomponent_new(ICAL_VTODO_COMPONENT);
1474 icalcomponent* icalcomponent_new_vjournal()
1476 return icalcomponent_new(ICAL_VJOURNAL_COMPONENT);
1478 icalcomponent* icalcomponent_new_valarm()
1480 return icalcomponent_new(ICAL_VALARM_COMPONENT);
1482 icalcomponent* icalcomponent_new_vfreebusy()
1484 return icalcomponent_new(ICAL_VFREEBUSY_COMPONENT);
1486 icalcomponent* icalcomponent_new_vtimezone()
1488 return icalcomponent_new(ICAL_VTIMEZONE_COMPONENT);
1490 icalcomponent* icalcomponent_new_xstandard()
1492 return icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
1494 icalcomponent* icalcomponent_new_xdaylight()
1496 return icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);