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;
400 struct icalproperty_impl *pimpl;
402 icalerror_check_arg_rv( (component!=0), "component");
403 icalerror_check_arg_rv( (property!=0), "property");
405 impl = (struct icalcomponent_impl*)component;
407 pimpl = (struct icalproperty_impl*)property;
409 icalerror_assert( (icalproperty_get_parent(property)),"The property is not a member of a component");
412 for( itr = pvl_head(impl->properties);
416 next_itr = pvl_next(itr);
418 if( pvl_data(itr) == (void*)property ){
420 if (impl->property_iterator == itr){
421 impl->property_iterator = pvl_next(itr);
424 pvl_remove( impl->properties, itr);
425 icalproperty_set_parent(property,0);
431 icalcomponent_count_properties (icalcomponent* component,
432 icalproperty_kind kind)
436 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
438 icalerror_check_arg_rz( (component!=0), "component");
440 for( itr = pvl_head(impl->properties);
444 if(kind == icalproperty_isa((icalproperty*)pvl_data(itr)) ||
445 kind == ICAL_ANY_PROPERTY){
455 icalproperty* icalcomponent_get_current_property (icalcomponent* component)
458 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
459 icalerror_check_arg_rz( (component!=0),"component");
461 if ((c->property_iterator==0)){
465 return (icalproperty*) pvl_data(c->property_iterator);
470 icalcomponent_get_first_property (icalcomponent* component, icalproperty_kind kind)
472 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
473 icalerror_check_arg_rz( (component!=0),"component");
475 for( c->property_iterator = pvl_head(c->properties);
476 c->property_iterator != 0;
477 c->property_iterator = pvl_next(c->property_iterator)) {
479 icalproperty *p = (icalproperty*) pvl_data(c->property_iterator);
481 if (icalproperty_isa(p) == kind || kind == ICAL_ANY_PROPERTY) {
490 icalcomponent_get_next_property (icalcomponent* component, icalproperty_kind kind)
492 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
493 icalerror_check_arg_rz( (component!=0),"component");
495 if (c->property_iterator == 0){
499 for( c->property_iterator = pvl_next(c->property_iterator);
500 c->property_iterator != 0;
501 c->property_iterator = pvl_next(c->property_iterator)) {
503 icalproperty *p = (icalproperty*) pvl_data(c->property_iterator);
505 if (icalproperty_isa(p) == kind || kind == ICAL_ANY_PROPERTY) {
516 icalcomponent_get_properties (icalcomponent* component, icalproperty_kind kind);
520 icalcomponent_add_component (icalcomponent* parent, icalcomponent* child)
522 struct icalcomponent_impl *impl, *cimpl;
524 icalerror_check_arg_rv( (parent!=0), "parent");
525 icalerror_check_arg_rv( (child!=0), "child");
527 impl = (struct icalcomponent_impl*)parent;
528 cimpl = (struct icalcomponent_impl*)child;
530 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");
532 cimpl->parent = parent;
534 pvl_push(impl->components,child);
539 icalcomponent_remove_component (icalcomponent* parent, icalcomponent* child)
541 struct icalcomponent_impl *impl,*cimpl;
542 pvl_elem itr, next_itr;
544 icalerror_check_arg_rv( (parent!=0), "parent");
545 icalerror_check_arg_rv( (child!=0), "child");
547 impl = (struct icalcomponent_impl*)parent;
548 cimpl = (struct icalcomponent_impl*)child;
550 for( itr = pvl_head(impl->components);
554 next_itr = pvl_next(itr);
556 if( pvl_data(itr) == (void*)child ){
558 if (impl->component_iterator == itr){
559 /* Don't let the current iterator become invalid */
561 /* HACK. The semantics for this are troubling. */
562 impl->component_iterator =
563 pvl_next(impl->component_iterator);
566 pvl_remove( impl->components, itr);
575 icalcomponent_count_components (icalcomponent* component,
576 icalcomponent_kind kind)
580 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
582 icalerror_check_arg_rz( (component!=0), "component");
584 for( itr = pvl_head(impl->components);
588 if(kind == icalcomponent_isa((icalcomponent*)pvl_data(itr)) ||
589 kind == ICAL_ANY_COMPONENT){
598 icalcomponent_get_current_component(icalcomponent* component)
600 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
602 icalerror_check_arg_rz( (component!=0),"component");
604 if (c->component_iterator == 0){
608 return (icalcomponent*) pvl_data(c->component_iterator);
612 icalcomponent_get_first_component (icalcomponent* component,
613 icalcomponent_kind kind)
615 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
617 icalerror_check_arg_rz( (component!=0),"component");
619 for( c->component_iterator = pvl_head(c->components);
620 c->component_iterator != 0;
621 c->component_iterator = pvl_next(c->component_iterator)) {
623 icalcomponent *p = (icalcomponent*) pvl_data(c->component_iterator);
625 if (icalcomponent_isa(p) == kind || kind == ICAL_ANY_COMPONENT) {
636 icalcomponent_get_next_component (icalcomponent* component, icalcomponent_kind kind)
638 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
640 icalerror_check_arg_rz( (component!=0),"component");
642 if (c->component_iterator == 0){
646 for( c->component_iterator = pvl_next(c->component_iterator);
647 c->component_iterator != 0;
648 c->component_iterator = pvl_next(c->component_iterator)) {
650 icalcomponent *p = (icalcomponent*) pvl_data(c->component_iterator);
652 if (icalcomponent_isa(p) == kind || kind == ICAL_ANY_COMPONENT) {
661 icalcomponent* icalcomponent_get_first_real_component(icalcomponent *c)
665 for(comp = icalcomponent_get_first_component(c,ICAL_ANY_COMPONENT);
667 comp = icalcomponent_get_next_component(c,ICAL_ANY_COMPONENT)){
669 icalcomponent_kind kind = icalcomponent_isa(comp);
671 if(kind == ICAL_VEVENT_COMPONENT ||
672 kind == ICAL_VTODO_COMPONENT ||
673 kind == ICAL_VJOURNAL_COMPONENT ){
680 time_t icalcomponent_convert_time(icalproperty *p)
682 struct icaltimetype sict;
687 /* Though it says _dtstart, it will work for dtend too */
688 sict = icalproperty_get_dtstart(p);
690 tzp = icalproperty_get_first_parameter(p,ICAL_TZID_PARAMETER);
692 if (sict.is_utc == 1 && tzp != 0){
693 icalerror_warn("icalcomponent_get_span: component has a UTC DTSTART with a timezone specified ");
694 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
698 if(sict.is_utc == 1){
699 #ifdef TEST_CONVERT_TIME
702 /* _as_timet will use gmtime() to do the conversion */
703 convt = icaltime_as_timet(sict);
705 #ifdef TEST_CONVERT_TIME
706 printf("convert time: use as_timet:\n %s\n %s",
707 icalproperty_as_ical_string(p), ctime_r(&convt,buft));
710 } else if (sict.is_utc == 0 && tzp == 0 ) {
712 #ifdef TEST_CONVERT_TIME
716 /* _as_timet will use localtime() to do the conversion */
717 convt = icaltime_as_timet(sict);
718 offset = icaltime_utc_offset(sict,0);
721 #ifdef TEST_CONVERT_TIME
722 printf("convert time: use as_timet and adjust:\n %s\n %s",
723 icalproperty_as_ical_string(p), ctime_r(&convt,buft));
726 #ifdef TEST_CONVERT_TIME
729 /* Convert the time to UTC for the named timezone*/
730 const char* timezone = icalparameter_get_tzid(tzp);
731 convt = icaltime_as_timet(icaltime_as_utc(sict,timezone));
733 #ifdef TEST_CONVERT_TIME
734 printf("convert time: use _as_utc:\n %s\n %s",
735 icalproperty_as_ical_string(p), ctime_r(&convt,buft));
741 struct icaltime_span icalcomponent_get_span(icalcomponent* comp)
743 icalcomponent *inner;
744 icalproperty *p, *duration;
745 icalcomponent_kind kind;
746 struct icaltime_span span;
747 struct icaltimetype start;
748 #ifdef TEST_CONVERT_TIME
756 /* initial Error checking */
758 /* icalerror_check_arg_rz( (comp!=0),"comp");*/
760 kind = icalcomponent_isa(comp);
762 if(kind == ICAL_VCALENDAR_COMPONENT){
763 inner = icalcomponent_get_first_real_component(comp);
765 /* Maybe there is a VTIMEZONE in there */
767 inner = icalcomponent_get_first_component(comp,
768 ICAL_VTIMEZONE_COMPONENT);
776 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
777 /*icalerror_warn("icalcomponent_get_span: no component specified, or empty VCALENDAR component");*/
781 kind = icalcomponent_isa(inner);
783 if( !( kind == ICAL_VEVENT_COMPONENT ||
784 kind == ICAL_VJOURNAL_COMPONENT ||
785 kind == ICAL_VTODO_COMPONENT ||
786 kind == ICAL_VFREEBUSY_COMPONENT )) {
787 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
788 /*icalerror_warn("icalcomponent_get_span: no component specified, or empty VCALENDAR component");*/
795 /* Get to work. starting with DTSTART */
797 p = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY);
800 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
801 /*icalerror_warn("icalcomponent_get_span: component has no DTSTART time");*/
806 start = icalproperty_get_dtstart(p);
808 icalerror_clear_errno();
810 span.start = icalcomponent_convert_time(p);
812 #ifdef TEST_CONVERT_TIME
813 printf("convert time:\n %s %s",
814 icalproperty_as_ical_string(p), ctime_r(&span.start, buft));
817 if(icalerrno != ICAL_NO_ERROR){
822 /* The end time could be specified as either a DTEND or a DURATION */
823 p = icalcomponent_get_first_property(inner, ICAL_DTEND_PROPERTY);
824 duration = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
826 if (p==0 && duration == 0 && start.is_date != 1) {
827 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
828 /*icalerror_warn("icalcomponent_get_span: component has neither DTEND nor DURATION time");*/
834 span.end = icalcomponent_convert_time(p);
835 } else if (start.is_date == 1) {
836 /* Duration is all day */
837 span.end = span.start + 60*60*24;
839 /* Use the duration */
840 struct icaldurationtype dur;
844 dur = icalproperty_get_duration(duration);
846 durt = icaldurationtype_as_int(dur);
847 span.end = span.start+durt;
855 int icalcomponent_count_errors(icalcomponent* component)
861 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
863 for( itr = pvl_head(impl->properties);
867 p = (icalproperty*)pvl_data(itr);
869 if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
876 for( itr = pvl_head(impl->components);
880 c = (icalcomponent*)pvl_data(itr);
882 errors += icalcomponent_count_errors(c);
890 void icalcomponent_strip_errors(icalcomponent* component)
894 pvl_elem itr, next_itr;
895 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
897 for( itr = pvl_head(impl->properties);
901 p = (icalproperty*)pvl_data(itr);
902 next_itr = pvl_next(itr);
904 if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
906 icalcomponent_remove_property(component,p);
910 for( itr = pvl_head(impl->components);
914 c = (icalcomponent*)pvl_data(itr);
915 icalcomponent_strip_errors(c);
919 /* Hack. This will change the state of the iterators */
920 void icalcomponent_convert_errors(icalcomponent* component)
922 icalproperty *p, *next_p;
925 for(p = icalcomponent_get_first_property(component,ICAL_ANY_PROPERTY);
929 next_p = icalcomponent_get_next_property(component,ICAL_ANY_PROPERTY);
931 if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
933 struct icalreqstattype rst;
934 icalparameter *param = icalproperty_get_first_parameter
935 (p,ICAL_XLICERRORTYPE_PARAMETER);
937 rst.code = ICAL_UNKNOWN_STATUS;
940 switch(icalparameter_get_xlicerrortype(param)){
942 case ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR: {
943 rst.code = ICAL_3_2_INVPARAM_STATUS;
946 case ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR: {
947 rst.code = ICAL_3_3_INVPARAMVAL_STATUS;
950 case ICAL_XLICERRORTYPE_PROPERTYPARSEERROR: {
951 rst.code = ICAL_3_0_INVPROPNAME_STATUS;
954 case ICAL_XLICERRORTYPE_VALUEPARSEERROR: {
955 rst.code = ICAL_3_1_INVPROPVAL_STATUS;
958 case ICAL_XLICERRORTYPE_COMPONENTPARSEERROR: {
959 rst.code = ICAL_3_4_INVCOMP_STATUS;
966 if (rst.code != ICAL_UNKNOWN_STATUS){
968 rst.debug = icalproperty_get_xlicerror(p);
969 icalcomponent_add_property(component,
970 icalproperty_new_requeststatus(
971 icalreqstattype_as_string(rst)
975 icalcomponent_remove_property(component,p);
980 for(c = icalcomponent_get_first_component(component,ICAL_ANY_COMPONENT);
982 c = icalcomponent_get_next_component(component,ICAL_ANY_COMPONENT)){
984 icalcomponent_convert_errors(c);
989 icalcomponent* icalcomponent_get_parent(icalcomponent* component)
991 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
996 void icalcomponent_set_parent(icalcomponent* component, icalcomponent* parent)
998 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
1003 icalcompiter icalcompiter_null = {ICAL_NO_COMPONENT,0};
1006 struct icalcomponent_kind_map {
1007 icalcomponent_kind kind;
1013 static struct icalcomponent_kind_map component_map[] =
1015 { ICAL_VEVENT_COMPONENT, "VEVENT" },
1016 { ICAL_VTODO_COMPONENT, "VTODO" },
1017 { ICAL_VJOURNAL_COMPONENT, "VJOURNAL" },
1018 { ICAL_VCALENDAR_COMPONENT, "VCALENDAR" },
1019 { ICAL_VFREEBUSY_COMPONENT, "VFREEBUSY" },
1020 { ICAL_VTIMEZONE_COMPONENT, "VTIMEZONE" },
1021 { ICAL_VALARM_COMPONENT, "VALARM" },
1022 { ICAL_XSTANDARD_COMPONENT, "STANDARD" }, /*These are part of RFC2445 */
1023 { ICAL_XDAYLIGHT_COMPONENT, "DAYLIGHT" }, /*but are not really components*/
1024 { ICAL_X_COMPONENT, "X" },
1025 { ICAL_VSCHEDULE_COMPONENT, "SCHEDULE" },
1027 /* CAP components */
1028 { ICAL_VQUERY_COMPONENT, "VQUERY" },
1029 { ICAL_VCAR_COMPONENT, "VCAR" },
1030 { ICAL_VCOMMAND_COMPONENT, "VCOMMAND" },
1032 /* libical private components */
1033 { ICAL_XLICINVALID_COMPONENT, "X-LIC-UNKNOWN" },
1034 { ICAL_XLICMIMEPART_COMPONENT, "X-LIC-MIME-PART" },
1035 { ICAL_ANY_COMPONENT, "ANY" },
1036 { ICAL_XROOT_COMPONENT, "XROOT" },
1039 { ICAL_NO_COMPONENT, "" },
1044 const char* icalcomponent_kind_to_string(icalcomponent_kind kind)
1048 for (i=0; component_map[i].kind != ICAL_NO_COMPONENT; i++) {
1049 if (component_map[i].kind == kind) {
1050 return component_map[i].name;
1058 icalcomponent_kind icalcomponent_string_to_kind(const char* string)
1063 return ICAL_NO_COMPONENT;
1066 for (i=0; component_map[i].kind != ICAL_NO_COMPONENT; i++) {
1067 if (strcmp(component_map[i].name, string) == 0) {
1068 return component_map[i].kind;
1072 return ICAL_NO_COMPONENT;
1078 icalcomponent_begin_component(icalcomponent* component,icalcomponent_kind kind)
1080 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
1086 icalerror_check_arg_re( (component!=0),"component",icalcompiter_null);
1088 for( i = pvl_head(impl->components); i != 0; i = pvl_next(itr.iter)) {
1090 icalcomponent *c = (icalcomponent*) pvl_data(i);
1092 if (icalcomponent_isa(c) == kind || kind == ICAL_ANY_COMPONENT) {
1100 return icalcompiter_null;
1104 icalcomponent_end_component(icalcomponent* component,icalcomponent_kind kind)
1106 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
1112 icalerror_check_arg_re( (component!=0),"component",icalcompiter_null);
1114 for( i = pvl_tail(impl->components); i != 0; i = pvl_prior(i)) {
1116 icalcomponent *c = (icalcomponent*) pvl_data(i);
1118 if (icalcomponent_isa(c) == kind || kind == ICAL_ANY_COMPONENT) {
1120 itr.iter = pvl_next(i);
1126 return icalcompiter_null;;
1130 icalcomponent* icalcompiter_next(icalcompiter* i)
1136 icalerror_check_arg_rz( (i!=0),"i");
1138 for( i->iter = pvl_next(i->iter);
1140 i->iter = pvl_next(i->iter)) {
1142 icalcomponent *c = (icalcomponent*) pvl_data(i->iter);
1144 if (icalcomponent_isa(c) == i->kind
1145 || i->kind == ICAL_ANY_COMPONENT) {
1147 return icalcompiter_deref(i);;
1155 icalcomponent* icalcompiter_prior(icalcompiter* i)
1161 for( i->iter = pvl_prior(i->iter);
1163 i->iter = pvl_prior(i->iter)) {
1165 icalcomponent *c = (icalcomponent*) pvl_data(i->iter);
1167 if (icalcomponent_isa(c) == i->kind
1168 || i->kind == ICAL_ANY_COMPONENT) {
1170 return icalcompiter_deref(i);;
1177 icalcomponent* icalcompiter_deref(icalcompiter* i)
1183 return pvl_data(i->iter);
1186 icalcomponent* icalcomponent_get_inner(icalcomponent* comp)
1188 if (icalcomponent_isa(comp) == ICAL_VCALENDAR_COMPONENT){
1189 return icalcomponent_get_first_real_component(comp);
1196 void icalcomponent_set_dtstart(icalcomponent* comp, struct icaltimetype v)
1199 icalcomponent *inner = icalcomponent_get_inner(comp);
1201 = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY);
1205 prop = icalproperty_new_dtstart(v);
1206 icalcomponent_add_property(inner, prop);
1209 icalproperty_set_dtstart(prop,v);
1214 struct icaltimetype icalcomponent_get_dtstart(icalcomponent* comp)
1216 icalcomponent *inner = icalcomponent_get_inner(comp);
1218 = icalcomponent_get_first_property(inner,ICAL_DTSTART_PROPERTY);
1221 return icaltime_null_time();
1224 return icalproperty_get_dtstart(prop);
1228 struct icaltimetype icalcomponent_get_dtend(icalcomponent* comp)
1230 icalcomponent *inner = icalcomponent_get_inner(comp);
1232 icalproperty *end_prop
1233 = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
1235 icalproperty *dur_prop
1236 = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
1239 if( end_prop == 0 && dur_prop == 0){
1240 return icaltime_null_time();
1241 } else if ( end_prop != 0) {
1242 return icalproperty_get_dtend(end_prop);
1243 } else if ( dur_prop != 0) {
1245 struct icaltimetype start =
1246 icalcomponent_get_dtstart(inner);
1247 struct icaldurationtype duration =
1248 icalproperty_get_duration(dur_prop);
1250 struct icaltimetype end = icaltime_add(start,duration);
1255 /* Error, both duration and dtend have been specified */
1256 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1257 return icaltime_null_time();
1264 void icalcomponent_set_dtend(icalcomponent* comp, struct icaltimetype v)
1266 icalcomponent *inner = icalcomponent_get_inner(comp);
1268 icalproperty *end_prop
1269 = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
1271 icalproperty *dur_prop
1272 = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
1275 if( end_prop == 0 && dur_prop == 0){
1276 end_prop = icalproperty_new_dtend(v);
1277 icalcomponent_add_property(inner,end_prop);
1278 } else if ( end_prop != 0) {
1279 icalproperty_set_dtend(end_prop,v);
1280 } else if ( dur_prop != 0) {
1281 struct icaltimetype start =
1282 icalcomponent_get_dtstart(inner);
1284 struct icaltimetype end =
1285 icalcomponent_get_dtend(inner);
1287 struct icaldurationtype dur
1288 = icaltime_subtract(end,start);
1290 icalproperty_set_duration(dur_prop,dur);
1293 /* Error, both duration and dtend have been specified */
1294 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1298 void icalcomponent_set_duration(icalcomponent* comp,
1299 struct icaldurationtype v)
1301 icalcomponent *inner = icalcomponent_get_inner(comp);
1303 icalproperty *end_prop
1304 = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
1306 icalproperty *dur_prop
1307 = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
1310 if( end_prop == 0 && dur_prop == 0){
1311 dur_prop = icalproperty_new_duration(v);
1312 icalcomponent_add_property(inner, dur_prop);
1313 } else if ( end_prop != 0) {
1314 struct icaltimetype start =
1315 icalcomponent_get_dtstart(inner);
1317 struct icaltimetype new_end = icaltime_add(start,v);
1319 icalproperty_set_dtend(end_prop,new_end);
1321 } else if ( dur_prop != 0) {
1322 icalproperty_set_duration(dur_prop,v);
1324 /* Error, both duration and dtend have been specified */
1325 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1329 struct icaldurationtype icalcomponent_get_duration(icalcomponent* comp)
1331 icalcomponent *inner = icalcomponent_get_inner(comp);
1333 icalproperty *end_prop
1334 = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
1336 icalproperty *dur_prop
1337 = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
1339 struct icaldurationtype null_duration;
1340 memset(&null_duration,0,sizeof(struct icaldurationtype));
1343 if( end_prop == 0 && dur_prop == 0){
1344 return null_duration;
1345 } else if ( end_prop != 0) {
1346 struct icaltimetype start =
1347 icalcomponent_get_dtstart(inner);
1348 time_t startt = icaltime_as_timet(start);
1350 struct icaltimetype end =
1351 icalcomponent_get_dtend(inner);
1352 time_t endt = icaltime_as_timet(end);
1354 return icaldurationtype_from_int(endt-startt);
1355 } else if ( dur_prop != 0) {
1356 return icalproperty_get_duration(dur_prop);
1358 /* Error, both duration and dtend have been specified */
1359 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1360 return null_duration;
1364 void icalcomponent_set_method(icalcomponent* comp, icalproperty_method method)
1367 = icalcomponent_get_first_property(comp, ICAL_METHOD_PROPERTY);
1371 prop = icalproperty_new_method(method);
1372 icalcomponent_add_property(comp, prop);
1375 icalproperty_set_method(prop,method);
1379 icalproperty_method icalcomponent_get_method(icalcomponent* comp)
1382 = icalcomponent_get_first_property(comp,ICAL_METHOD_PROPERTY);
1385 return ICAL_METHOD_NONE;
1388 return icalproperty_get_method(prop);
1391 void icalcomponent_set_dtstamp(icalcomponent* comp, struct icaltimetype v)
1394 icalcomponent *inner = icalcomponent_get_inner(comp);
1396 = icalcomponent_get_first_property(inner, ICAL_DTSTAMP_PROPERTY);
1400 prop = icalproperty_new_dtstamp(v);
1401 icalcomponent_add_property(inner, prop);
1404 icalproperty_set_dtstamp(prop,v);
1409 struct icaltimetype icalcomponent_get_dtstamp(icalcomponent* comp)
1411 icalcomponent *inner = icalcomponent_get_inner(comp);
1413 = icalcomponent_get_first_property(inner,ICAL_DTSTAMP_PROPERTY);
1416 return icaltime_null_time();
1419 return icalproperty_get_dtstamp(prop);
1423 void icalcomponent_set_summary(icalcomponent* comp, const char* v)
1425 icalcomponent *inner = icalcomponent_get_inner(comp);
1427 = icalcomponent_get_first_property(inner, ICAL_SUMMARY_PROPERTY);
1430 prop = icalproperty_new_summary(v);
1431 icalcomponent_add_property(inner, prop);
1434 icalproperty_set_summary(prop,v);
1438 const char* icalcomponent_get_summary(icalcomponent* comp)
1440 icalcomponent *inner = icalcomponent_get_inner(comp);
1442 = icalcomponent_get_first_property(inner,ICAL_SUMMARY_PROPERTY);
1448 return icalproperty_get_summary(prop);
1452 void icalcomponent_set_comment(icalcomponent* comp, const char* v);
1453 const char* icalcomponent_get_comment(icalcomponent* comp);
1455 void icalcomponent_set_uid(icalcomponent* comp, const char* v);
1456 const char* icalcomponent_get_uid(icalcomponent* comp);
1458 void icalcomponent_set_recurrenceid(icalcomponent* comp,
1459 struct icaltimetype v);
1460 struct icaltimetype icalcomponent_get_recurrenceid(icalcomponent* comp);
1465 icalcomponent* icalcomponent_new_vcalendar()
1467 return icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
1469 icalcomponent* icalcomponent_new_vevent()
1471 return icalcomponent_new(ICAL_VEVENT_COMPONENT);
1473 icalcomponent* icalcomponent_new_vtodo()
1475 return icalcomponent_new(ICAL_VTODO_COMPONENT);
1477 icalcomponent* icalcomponent_new_vjournal()
1479 return icalcomponent_new(ICAL_VJOURNAL_COMPONENT);
1481 icalcomponent* icalcomponent_new_valarm()
1483 return icalcomponent_new(ICAL_VALARM_COMPONENT);
1485 icalcomponent* icalcomponent_new_vfreebusy()
1487 return icalcomponent_new(ICAL_VFREEBUSY_COMPONENT);
1489 icalcomponent* icalcomponent_new_vtimezone()
1491 return icalcomponent_new(ICAL_VTIMEZONE_COMPONENT);
1493 icalcomponent* icalcomponent_new_xstandard()
1495 return icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
1497 icalcomponent* icalcomponent_new_xdaylight()
1499 return icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);