summaryrefslogtreecommitdiffabout
path: root/libical/src/libical/icalcomponent.c
Unidiff
Diffstat (limited to 'libical/src/libical/icalcomponent.c') (more/less context) (show whitespace changes)
-rw-r--r--libical/src/libical/icalcomponent.c1488
1 files changed, 1488 insertions, 0 deletions
diff --git a/libical/src/libical/icalcomponent.c b/libical/src/libical/icalcomponent.c
new file mode 100644
index 0000000..af0d3ec
--- a/dev/null
+++ b/libical/src/libical/icalcomponent.c
@@ -0,0 +1,1488 @@
1/*======================================================================
2 FILE: icalcomponent.c
3 CREATOR: eric 28 April 1999
4
5 $Id$
6
7
8 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of either:
12
13 The LGPL as published by the Free Software Foundation, version
14 2.1, available at: http://www.fsf.org/copyleft/lesser.html
15
16 Or:
17
18 The Mozilla Public License Version 1.0. You may obtain a copy of
19 the License at http://www.mozilla.org/MPL/
20
21 The original code is icalcomponent.c
22
23======================================================================*/
24
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#include "icalcomponent.h"
31#include "pvl.h" /* "Pointer-to-void list" */
32#include "icalerror.h"
33#include "icalmemory.h"
34#include "icalenums.h"
35#include "icaltime.h"
36#include "icalduration.h"
37#include "icalperiod.h"
38#include "icalparser.h"
39
40#include <stdlib.h> /* for malloc */
41#include <stdarg.h> /* for va_list, etc */
42#include <errno.h>
43#include <assert.h>
44#include <stdio.h> /* for fprintf */
45#include <string.h>
46
47#define MAX_TMP 1024
48
49struct icalcomponent_impl
50{
51 char id[5];
52 icalcomponent_kind kind;
53 char* x_name;
54 pvl_list properties;
55 pvl_elem property_iterator;
56 pvl_list components;
57 pvl_elem component_iterator;
58 icalcomponent* parent;
59};
60
61/* icalproperty functions that only components get to use */
62void icalproperty_set_parent(icalproperty* property,
63 icalcomponent* component);
64icalcomponent* icalproperty_get_parent(icalproperty* property);
65void icalcomponent_add_children(struct icalcomponent_impl *impl,va_list args);
66icalcomponent* icalcomponent_new_impl (icalcomponent_kind kind);
67int icalcomponent_property_sorter(void *a, void *b);
68
69
70void icalcomponent_add_children(struct icalcomponent_impl *impl,va_list args)
71{
72 void* vp;
73
74 while((vp = va_arg(args, void*)) != 0) {
75
76 assert (icalcomponent_isa_component(vp) != 0 ||
77 icalproperty_isa_property(vp) != 0 ) ;
78
79 if (icalcomponent_isa_component(vp) != 0 ){
80
81 icalcomponent_add_component((icalcomponent*)impl,
82 (icalcomponent*)vp);
83
84 } else if (icalproperty_isa_property(vp) != 0 ){
85
86 icalcomponent_add_property((icalcomponent*)impl,
87 (icalproperty*)vp);
88 }
89 }
90}
91
92icalcomponent*
93icalcomponent_new_impl (icalcomponent_kind kind)
94{
95 struct icalcomponent_impl* comp;
96
97 if ( ( comp = (struct icalcomponent_impl*)
98 malloc(sizeof(struct icalcomponent_impl))) == 0) {
99 icalerror_set_errno(ICAL_NEWFAILED_ERROR);
100 return 0;
101 }
102
103 strcpy(comp->id,"comp");
104
105 comp->kind = kind;
106 comp->properties = pvl_newlist();
107 comp->property_iterator = 0;
108 comp->components = pvl_newlist();
109 comp->component_iterator = 0;
110 comp->x_name = 0;
111 comp->parent = 0;
112
113 return comp;
114}
115
116icalcomponent*
117icalcomponent_new (icalcomponent_kind kind)
118{
119 return (icalcomponent*)icalcomponent_new_impl(kind);
120}
121
122icalcomponent*
123icalcomponent_vanew (icalcomponent_kind kind, ...)
124{
125 va_list args;
126
127 struct icalcomponent_impl *impl = icalcomponent_new_impl(kind);
128
129 if (impl == 0){
130 return 0;
131 }
132
133 va_start(args,kind);
134 icalcomponent_add_children(impl, args);
135 va_end(args);
136
137 return (icalcomponent*) impl;
138}
139
140icalcomponent* icalcomponent_new_from_string(char* str)
141{
142 return icalparser_parse_string(str);
143}
144
145icalcomponent* icalcomponent_new_clone(icalcomponent* component)
146{
147 struct icalcomponent_impl *old = (struct icalcomponent_impl*)component;
148 struct icalcomponent_impl *new;
149 icalproperty *p;
150 icalcomponent *c;
151 pvl_elem itr;
152
153 icalerror_check_arg_rz( (component!=0), "component");
154
155 new = icalcomponent_new_impl(old->kind);
156
157 if (new == 0){
158 return 0;
159 }
160
161
162 for( itr = pvl_head(old->properties);
163 itr != 0;
164 itr = pvl_next(itr))
165 {
166 p = (icalproperty*)pvl_data(itr);
167 icalcomponent_add_property(new,icalproperty_new_clone(p));
168 }
169
170
171 for( itr = pvl_head(old->components);
172 itr != 0;
173 itr = pvl_next(itr))
174 {
175 c = (icalcomponent*)pvl_data(itr);
176 icalcomponent_add_component(new,icalcomponent_new_clone(c));
177 }
178
179 return new;
180
181}
182
183
184void
185icalcomponent_free (icalcomponent* component)
186{
187 icalproperty* prop;
188 icalcomponent* comp;
189 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
190
191 icalerror_check_arg_rv( (component!=0), "component");
192
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");
195#else
196 if(c->parent != 0){
197 return;
198 }
199#endif
200
201 if(component != 0 ){
202
203 while( (prop=pvl_pop(c->properties)) != 0){
204 assert(prop != 0);
205 icalproperty_set_parent(prop,0);
206 icalproperty_free(prop);
207 }
208
209 pvl_free(c->properties);
210
211 while( (comp=pvl_data(pvl_head(c->components))) != 0){
212 assert(comp!=0);
213 icalcomponent_remove_component(component,comp);
214 icalcomponent_free(comp);
215 }
216
217 pvl_free(c->components);
218
219 if (c->x_name != 0) {
220 free(c->x_name);
221 }
222
223 c->kind = ICAL_NO_COMPONENT;
224 c->properties = 0;
225 c->property_iterator = 0;
226 c->components = 0;
227 c->component_iterator = 0;
228 c->x_name = 0;
229 c->id[0] = 'X';
230
231 free(c);
232 }
233}
234
235char*
236icalcomponent_as_ical_string (icalcomponent* component)
237{
238 char* buf, *out_buf;
239 const char* tmp_buf;
240 size_t buf_size = 1024;
241 char* buf_ptr = 0;
242 pvl_elem itr;
243 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
244
245#ifdef ICAL_UNIX_NEWLINE
246 char newline[] = "\n";
247#else
248 char newline[] = "\n";
249#endif
250 icalcomponent *c;
251 icalproperty *p;
252 icalcomponent_kind kind = icalcomponent_isa(component);
253
254 const char* kind_string;
255
256 buf = icalmemory_new_buffer(buf_size);
257 buf_ptr = buf;
258
259 icalerror_check_arg_rz( (component!=0), "component");
260 icalerror_check_arg_rz( (kind!=ICAL_NO_COMPONENT), "component kind is ICAL_NO_COMPONENT");
261
262 kind_string = icalcomponent_kind_to_string(kind);
263
264 icalerror_check_arg_rz( (kind_string!=0),"Unknown kind of component");
265
266 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "BEGIN:");
267 icalmemory_append_string(&buf, &buf_ptr, &buf_size, kind_string);
268 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline);
269
270
271 for( itr = pvl_head(impl->properties);
272 itr != 0;
273 itr = pvl_next(itr))
274 {
275 // printf("3333calcomponent_as_ical_string System Timezone2: %s %s \n", *tzname, getenv("TZ") );
276
277 p = (icalproperty*)pvl_data(itr);
278
279 icalerror_assert((p!=0),"Got a null property");
280 tmp_buf = icalproperty_as_ical_string(p);
281
282 icalmemory_append_string(&buf, &buf_ptr, &buf_size, tmp_buf);
283 }
284
285
286 for( itr = pvl_head(impl->components);
287 itr != 0;
288 itr = pvl_next(itr))
289 {
290
291 c = (icalcomponent*)pvl_data(itr);
292
293 tmp_buf = icalcomponent_as_ical_string(c);
294 icalmemory_append_string(&buf, &buf_ptr, &buf_size, tmp_buf);
295
296 }
297
298 icalmemory_append_string(&buf, &buf_ptr, &buf_size, "END:"); //tzset();
299 icalmemory_append_string(&buf, &buf_ptr, &buf_size,
300 icalcomponent_kind_to_string(kind));
301 icalmemory_append_string(&buf, &buf_ptr, &buf_size, newline); //tzset();
302
303 out_buf = icalmemory_tmp_copy(buf);
304 free(buf);
305
306 return out_buf;
307}
308
309
310int
311icalcomponent_is_valid (icalcomponent* component)
312{
313 struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component;
314
315
316 if ( (strcmp(impl->id,"comp") == 0) &&
317 impl->kind != ICAL_NO_COMPONENT){
318 return 1;
319 } else {
320 return 0;
321 }
322
323}
324
325
326icalcomponent_kind
327icalcomponent_isa (icalcomponent* component)
328{
329 struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component;
330 icalerror_check_arg_rz( (component!=0), "component");
331
332 if(component != 0)
333 {
334 return impl->kind;
335 }
336
337 return ICAL_NO_COMPONENT;
338}
339
340
341int
342icalcomponent_isa_component (void* component)
343{
344 struct icalcomponent_impl *impl = (struct icalcomponent_impl *)component;
345
346 icalerror_check_arg_rz( (component!=0), "component");
347
348 if (strcmp(impl->id,"comp") == 0) {
349 return 1;
350 } else {
351 return 0;
352 }
353
354}
355
356int icalcomponent_property_sorter(void *a, void *b)
357{
358 icalproperty_kind kinda, kindb;
359 const char *ksa, *ksb;
360
361 kinda = icalproperty_isa((icalproperty*)a);
362 kindb = icalproperty_isa((icalproperty*)b);
363
364 ksa = icalproperty_kind_to_string(kinda);
365 ksb = icalproperty_kind_to_string(kindb);
366
367 return strcmp(ksa,ksb);
368}
369
370
371void
372icalcomponent_add_property (icalcomponent* component, icalproperty* property)
373{
374 struct icalcomponent_impl *impl;
375
376 icalerror_check_arg_rv( (component!=0), "component");
377 icalerror_check_arg_rv( (property!=0), "property");
378
379 impl = (struct icalcomponent_impl*)component;
380
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");
382
383 icalproperty_set_parent(property,component);
384
385#ifdef ICAL_INSERT_ORDERED
386 pvl_insert_ordered(impl->properties,
387 icalcomponent_property_sorter,property);
388#else
389 pvl_push(impl->properties,property);
390#endif
391
392}
393
394
395void
396icalcomponent_remove_property (icalcomponent* component, icalproperty* property)
397{
398 struct icalcomponent_impl *impl;
399 pvl_elem itr, next_itr;
400 struct icalproperty_impl *pimpl;
401
402 icalerror_check_arg_rv( (component!=0), "component");
403 icalerror_check_arg_rv( (property!=0), "property");
404
405 impl = (struct icalcomponent_impl*)component;
406
407 pimpl = (struct icalproperty_impl*)property;
408
409 icalerror_assert( (icalproperty_get_parent(property)),"The property is not a member of a component");
410
411
412 for( itr = pvl_head(impl->properties);
413 itr != 0;
414 itr = next_itr)
415 {
416 next_itr = pvl_next(itr);
417
418 if( pvl_data(itr) == (void*)property ){
419
420 if (impl->property_iterator == itr){
421 impl->property_iterator = pvl_next(itr);
422 }
423
424 pvl_remove( impl->properties, itr);
425 icalproperty_set_parent(property,0);
426 }
427 }
428}
429
430int
431icalcomponent_count_properties (icalcomponent* component,
432 icalproperty_kind kind)
433{
434 int count=0;
435 pvl_elem itr;
436 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
437
438 icalerror_check_arg_rz( (component!=0), "component");
439
440 for( itr = pvl_head(impl->properties);
441 itr != 0;
442 itr = pvl_next(itr))
443 {
444 if(kind == icalproperty_isa((icalproperty*)pvl_data(itr)) ||
445 kind == ICAL_ANY_PROPERTY){
446 count++;
447 }
448 }
449
450
451 return count;
452
453}
454
455icalproperty* icalcomponent_get_current_property (icalcomponent* component)
456{
457
458 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
459 icalerror_check_arg_rz( (component!=0),"component");
460
461 if ((c->property_iterator==0)){
462 return 0;
463 }
464
465 return (icalproperty*) pvl_data(c->property_iterator);
466
467}
468
469icalproperty*
470icalcomponent_get_first_property (icalcomponent* component, icalproperty_kind kind)
471{
472 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
473 icalerror_check_arg_rz( (component!=0),"component");
474
475 for( c->property_iterator = pvl_head(c->properties);
476 c->property_iterator != 0;
477 c->property_iterator = pvl_next(c->property_iterator)) {
478
479 icalproperty *p = (icalproperty*) pvl_data(c->property_iterator);
480
481 if (icalproperty_isa(p) == kind || kind == ICAL_ANY_PROPERTY) {
482
483 return p;
484 }
485 }
486 return 0;
487}
488
489icalproperty*
490icalcomponent_get_next_property (icalcomponent* component, icalproperty_kind kind)
491{
492 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
493 icalerror_check_arg_rz( (component!=0),"component");
494
495 if (c->property_iterator == 0){
496 return 0;
497 }
498
499 for( c->property_iterator = pvl_next(c->property_iterator);
500 c->property_iterator != 0;
501 c->property_iterator = pvl_next(c->property_iterator)) {
502
503 icalproperty *p = (icalproperty*) pvl_data(c->property_iterator);
504
505 if (icalproperty_isa(p) == kind || kind == ICAL_ANY_PROPERTY) {
506
507 return p;
508 }
509 }
510
511 return 0;
512}
513
514
515icalproperty**
516icalcomponent_get_properties (icalcomponent* component, icalproperty_kind kind);
517
518
519void
520icalcomponent_add_component (icalcomponent* parent, icalcomponent* child)
521{
522 struct icalcomponent_impl *impl, *cimpl;
523
524 icalerror_check_arg_rv( (parent!=0), "parent");
525 icalerror_check_arg_rv( (child!=0), "child");
526
527 impl = (struct icalcomponent_impl*)parent;
528 cimpl = (struct icalcomponent_impl*)child;
529
530 if (cimpl->parent !=0) {
531 icalerror_set_errno(ICAL_USAGE_ERROR);
532 }
533
534 cimpl->parent = parent;
535
536 pvl_push(impl->components,child);
537}
538
539
540void
541icalcomponent_remove_component (icalcomponent* parent, icalcomponent* child)
542{
543 struct icalcomponent_impl *impl,*cimpl;
544 pvl_elem itr, next_itr;
545
546 icalerror_check_arg_rv( (parent!=0), "parent");
547 icalerror_check_arg_rv( (child!=0), "child");
548
549 impl = (struct icalcomponent_impl*)parent;
550 cimpl = (struct icalcomponent_impl*)child;
551
552 for( itr = pvl_head(impl->components);
553 itr != 0;
554 itr = next_itr)
555 {
556 next_itr = pvl_next(itr);
557
558 if( pvl_data(itr) == (void*)child ){
559
560 if (impl->component_iterator == itr){
561 /* Don't let the current iterator become invalid */
562
563 /* HACK. The semantics for this are troubling. */
564 impl->component_iterator =
565 pvl_next(impl->component_iterator);
566
567 }
568 pvl_remove( impl->components, itr);
569 cimpl->parent = 0;
570 break;
571 }
572 }
573}
574
575
576int
577icalcomponent_count_components (icalcomponent* component,
578 icalcomponent_kind kind)
579{
580 int count=0;
581 pvl_elem itr;
582 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
583
584 icalerror_check_arg_rz( (component!=0), "component");
585
586 for( itr = pvl_head(impl->components);
587 itr != 0;
588 itr = pvl_next(itr))
589 {
590 if(kind == icalcomponent_isa((icalcomponent*)pvl_data(itr)) ||
591 kind == ICAL_ANY_COMPONENT){
592 count++;
593 }
594 }
595
596 return count;
597}
598
599icalcomponent*
600icalcomponent_get_current_component(icalcomponent* component)
601{
602 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
603
604 icalerror_check_arg_rz( (component!=0),"component");
605
606 if (c->component_iterator == 0){
607 return 0;
608 }
609
610 return (icalcomponent*) pvl_data(c->component_iterator);
611}
612
613icalcomponent*
614icalcomponent_get_first_component (icalcomponent* component,
615 icalcomponent_kind kind)
616{
617 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
618
619 icalerror_check_arg_rz( (component!=0),"component");
620
621 for( c->component_iterator = pvl_head(c->components);
622 c->component_iterator != 0;
623 c->component_iterator = pvl_next(c->component_iterator)) {
624
625 icalcomponent *p = (icalcomponent*) pvl_data(c->component_iterator);
626
627 if (icalcomponent_isa(p) == kind || kind == ICAL_ANY_COMPONENT) {
628
629 return p;
630 }
631 }
632
633 return 0;
634}
635
636
637icalcomponent*
638icalcomponent_get_next_component (icalcomponent* component, icalcomponent_kind kind)
639{
640 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
641
642 icalerror_check_arg_rz( (component!=0),"component");
643
644 if (c->component_iterator == 0){
645 return 0;
646 }
647
648 for( c->component_iterator = pvl_next(c->component_iterator);
649 c->component_iterator != 0;
650 c->component_iterator = pvl_next(c->component_iterator)) {
651
652 icalcomponent *p = (icalcomponent*) pvl_data(c->component_iterator);
653
654 if (icalcomponent_isa(p) == kind || kind == ICAL_ANY_COMPONENT) {
655
656 return p;
657 }
658 }
659
660 return 0;
661}
662
663icalcomponent* icalcomponent_get_first_real_component(icalcomponent *c)
664{
665 icalcomponent *comp;
666
667 for(comp = icalcomponent_get_first_component(c,ICAL_ANY_COMPONENT);
668 comp != 0;
669 comp = icalcomponent_get_next_component(c,ICAL_ANY_COMPONENT)){
670
671 icalcomponent_kind kind = icalcomponent_isa(comp);
672
673 if(kind == ICAL_VEVENT_COMPONENT ||
674 kind == ICAL_VTODO_COMPONENT ||
675 kind == ICAL_VJOURNAL_COMPONENT ||
676 kind == ICAL_VFREEBUSY_COMPONENT ){
677 return comp;
678 }
679 }
680 return 0;
681}
682
683time_t icalcomponent_convert_time(icalproperty *p)
684{
685 struct icaltimetype sict;
686 time_t convt;
687 icalproperty *tzp;
688
689
690 /* Though it says _dtstart, it will work for dtend too */
691 sict = icalproperty_get_dtstart(p);
692
693 tzp = icalproperty_get_first_parameter(p,ICAL_TZID_PARAMETER);
694
695 if (sict.is_utc == 1 && tzp != 0){
696 icalerror_warn("icalcomponent_get_span: component has a UTC DTSTART with a timezone specified ");
697 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
698 return 0;
699 }
700
701 if(sict.is_utc == 1){
702 /* _as_timet will use gmtime() to do the conversion */
703 convt = icaltime_as_timet(sict);
704
705#ifdef TEST_CONVERT_TIME
706 printf("convert time: use as_timet:\n %s\n %s",
707 icalproperty_as_ical_string(p), ctime(&convt));
708#endif
709
710 } else if (sict.is_utc == 0 && tzp == 0 ) {
711 time_t offset;
712
713 /* _as_timet will use localtime() to do the conversion */
714 convt = icaltime_as_timet(sict);
715 offset = icaltime_utc_offset(sict,0);
716 convt += offset;
717
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(&convt));
721#endif
722 } else {
723 /* Convert the time to UTC for the named timezone*/
724 const char* timezone = icalparameter_get_tzid(tzp);
725 convt = icaltime_as_timet(icaltime_as_utc(sict,timezone));
726
727#ifdef TEST_CONVERT_TIME
728 printf("convert time: use _as_utc:\n %s\n %s",
729 icalproperty_as_ical_string(p), ctime(&convt));
730#endif
731 }
732
733 return convt;
734}
735struct icaltime_span icalcomponent_get_span(icalcomponent* comp)
736{
737 icalcomponent *inner;
738 icalproperty *p, *duration;
739 icalcomponent_kind kind;
740 struct icaltime_span span;
741 struct icaltimetype start;
742
743 span.start = 0;
744 span.end = 0;
745 span.is_busy= 1;
746
747 /* initial Error checking */
748
749/* icalerror_check_arg_rz( (comp!=0),"comp");*/
750
751 kind = icalcomponent_isa(comp);
752
753 if(kind == ICAL_VCALENDAR_COMPONENT){
754 inner = icalcomponent_get_first_real_component(comp);
755
756 /* Maybe there is a VTIMEZONE in there */
757 if (inner == 0){
758 inner = icalcomponent_get_first_component(comp,
759 ICAL_VTIMEZONE_COMPONENT);
760 }
761
762 } else {
763 inner = comp;
764 }
765
766 if (inner == 0){
767 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
768 /*icalerror_warn("icalcomponent_get_span: no component specified, or empty VCALENDAR component");*/
769 return span;
770 }
771
772 kind = icalcomponent_isa(inner);
773
774 if( !( kind == ICAL_VEVENT_COMPONENT ||
775 kind == ICAL_VJOURNAL_COMPONENT ||
776 kind == ICAL_VTODO_COMPONENT ||
777 kind == ICAL_VFREEBUSY_COMPONENT )) {
778 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
779 /*icalerror_warn("icalcomponent_get_span: no component specified, or empty VCALENDAR component");*/
780 return span;
781
782 }
783
784
785
786 /* Get to work. starting with DTSTART */
787
788 p = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY);
789
790 if (p ==0 ) {
791 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
792 /*icalerror_warn("icalcomponent_get_span: component has no DTSTART time");*/
793 return span;
794 }
795
796
797 start = icalproperty_get_dtstart(p);
798
799 icalerror_clear_errno();
800
801 span.start = icalcomponent_convert_time(p);
802
803#ifdef TEST_CONVERT_TIME
804 printf("convert time:\n %s %s",
805 icalproperty_as_ical_string(p), ctime(&span.start));
806#endif
807
808 if(icalerrno != ICAL_NO_ERROR){
809 span.start = 0;
810 return span;
811 }
812
813 /* The end time could be specified as either a DTEND or a DURATION */
814 p = icalcomponent_get_first_property(inner, ICAL_DTEND_PROPERTY);
815 duration = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
816
817 if (p==0 && duration == 0 && start.is_date != 1) {
818 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
819 /*icalerror_warn("icalcomponent_get_span: component has neither DTEND nor DURATION time");*/
820 span.start = 0;
821 return span;
822 }
823
824 if (p!=0){
825 span.end = icalcomponent_convert_time(p);
826 } else if (start.is_date == 1) {
827 /* Duration is all day */
828 span.end = span.start + 60*60*24;
829 } else {
830 /* Use the duration */
831 struct icaldurationtype dur;
832 time_t durt;
833
834
835 dur = icalproperty_get_duration(duration);
836
837 durt = icaldurationtype_as_int(dur);
838 span.end = span.start+durt;
839 }
840
841 return span;
842
843}
844
845
846int icalcomponent_count_errors(icalcomponent* component)
847{
848 int errors = 0;
849 icalproperty *p;
850 icalcomponent *c;
851 pvl_elem itr;
852 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
853
854 for( itr = pvl_head(impl->properties);
855 itr != 0;
856 itr = pvl_next(itr))
857 {
858 p = (icalproperty*)pvl_data(itr);
859
860 if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
861 {
862 errors++;
863 }
864 }
865
866
867 for( itr = pvl_head(impl->components);
868 itr != 0;
869 itr = pvl_next(itr))
870 {
871 c = (icalcomponent*)pvl_data(itr);
872
873 errors += icalcomponent_count_errors(c);
874
875 }
876
877 return errors;
878}
879
880
881void icalcomponent_strip_errors(icalcomponent* component)
882{
883 icalproperty *p;
884 icalcomponent *c;
885 pvl_elem itr, next_itr;
886 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
887
888 for( itr = pvl_head(impl->properties);
889 itr != 0;
890 itr = next_itr)
891 {
892 p = (icalproperty*)pvl_data(itr);
893 next_itr = pvl_next(itr);
894
895 if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
896 {
897 icalcomponent_remove_property(component,p);
898 }
899 }
900
901 for( itr = pvl_head(impl->components);
902 itr != 0;
903 itr = pvl_next(itr))
904 {
905 c = (icalcomponent*)pvl_data(itr);
906 icalcomponent_strip_errors(c);
907 }
908}
909
910/* Hack. This will change the state of the iterators */
911void icalcomponent_convert_errors(icalcomponent* component)
912{
913 icalproperty *p, *next_p;
914 icalcomponent *c;
915
916 for(p = icalcomponent_get_first_property(component,ICAL_ANY_PROPERTY);
917 p != 0;
918 p = next_p){
919
920 next_p = icalcomponent_get_next_property(component,ICAL_ANY_PROPERTY);
921
922 if(icalproperty_isa(p) == ICAL_XLICERROR_PROPERTY)
923 {
924 struct icalreqstattype rst;
925 icalparameter *param = icalproperty_get_first_parameter
926 (p,ICAL_XLICERRORTYPE_PARAMETER);
927
928 rst.code = ICAL_UNKNOWN_STATUS;
929 rst.desc = 0;
930
931 switch(icalparameter_get_xlicerrortype(param)){
932
933 case ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR: {
934 rst.code = ICAL_3_2_INVPARAM_STATUS;
935 break;
936 }
937 case ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR: {
938 rst.code = ICAL_3_3_INVPARAMVAL_STATUS;
939 break;
940 }
941 case ICAL_XLICERRORTYPE_PROPERTYPARSEERROR: {
942 rst.code = ICAL_3_0_INVPROPNAME_STATUS;
943 break;
944 }
945 case ICAL_XLICERRORTYPE_VALUEPARSEERROR: {
946 rst.code = ICAL_3_1_INVPROPVAL_STATUS;
947 break;
948 }
949 case ICAL_XLICERRORTYPE_COMPONENTPARSEERROR: {
950 rst.code = ICAL_3_4_INVCOMP_STATUS;
951 break;
952 }
953
954 default: {
955 }
956 }
957 if (rst.code != ICAL_UNKNOWN_STATUS){
958
959 rst.debug = icalproperty_get_xlicerror(p);
960 icalcomponent_add_property(component,
961 icalproperty_new_requeststatus(rst));
962
963 icalcomponent_remove_property(component,p);
964 }
965 }
966 }
967
968 for(c = icalcomponent_get_first_component(component,ICAL_ANY_COMPONENT);
969 c != 0;
970 c = icalcomponent_get_next_component(component,ICAL_ANY_COMPONENT)){
971
972 icalcomponent_convert_errors(c);
973 }
974}
975
976
977icalcomponent* icalcomponent_get_parent(icalcomponent* component)
978{
979 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
980
981 return c->parent;
982}
983
984void icalcomponent_set_parent(icalcomponent* component, icalcomponent* parent)
985{
986 struct icalcomponent_impl *c = (struct icalcomponent_impl*)component;
987
988 c->parent = parent;
989}
990
991icalcompiter icalcompiter_null = {ICAL_NO_COMPONENT,0};
992
993
994struct icalcomponent_kind_map {
995 icalcomponent_kind kind;
996 char name[20];
997};
998
999
1000
1001static struct icalcomponent_kind_map component_map[] =
1002{
1003 { ICAL_VEVENT_COMPONENT, "VEVENT" },
1004 { ICAL_VTODO_COMPONENT, "VTODO" },
1005 { ICAL_VJOURNAL_COMPONENT, "VJOURNAL" },
1006 { ICAL_VCALENDAR_COMPONENT, "VCALENDAR" },
1007 { ICAL_VFREEBUSY_COMPONENT, "VFREEBUSY" },
1008 { ICAL_VTIMEZONE_COMPONENT, "VTIMEZONE" },
1009 { ICAL_VALARM_COMPONENT, "VALARM" },
1010 { ICAL_XSTANDARD_COMPONENT, "STANDARD" }, /*These are part of RFC2445 */
1011 { ICAL_XDAYLIGHT_COMPONENT, "DAYLIGHT" }, /*but are not really components*/
1012 { ICAL_X_COMPONENT, "X" },
1013 { ICAL_VSCHEDULE_COMPONENT, "SCHEDULE" },
1014
1015 /* CAP components */
1016 { ICAL_VQUERY_COMPONENT, "VQUERY" },
1017 { ICAL_VCAR_COMPONENT, "VCAR" },
1018 { ICAL_VCOMMAND_COMPONENT, "VCOMMAND" },
1019
1020 /* libical private components */
1021 { ICAL_XLICINVALID_COMPONENT, "X-LIC-UNKNOWN" },
1022 { ICAL_XLICMIMEPART_COMPONENT, "X-LIC-MIME-PART" },
1023 { ICAL_ANY_COMPONENT, "ANY" },
1024 { ICAL_XROOT_COMPONENT, "XROOT" },
1025
1026 /* End of list */
1027 { ICAL_NO_COMPONENT, "" },
1028};
1029
1030
1031
1032const char* icalcomponent_kind_to_string(icalcomponent_kind kind)
1033{
1034 int i;
1035
1036 for (i=0; component_map[i].kind != ICAL_NO_COMPONENT; i++) {
1037 if (component_map[i].kind == kind) {
1038 return component_map[i].name;
1039 }
1040 }
1041
1042 return 0;
1043
1044}
1045
1046icalcomponent_kind icalcomponent_string_to_kind(const char* string)
1047{
1048 int i;
1049
1050 if (string ==0 ) {
1051 return ICAL_NO_COMPONENT;
1052 }
1053
1054 for (i=0; component_map[i].kind != ICAL_NO_COMPONENT; i++) {
1055 if (strcmp(component_map[i].name, string) == 0) {
1056 return component_map[i].kind;
1057 }
1058 }
1059
1060 return ICAL_NO_COMPONENT;
1061}
1062
1063
1064
1065icalcompiter
1066icalcomponent_begin_component(icalcomponent* component,icalcomponent_kind kind)
1067{
1068 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
1069 icalcompiter itr = icalcompiter_null;
1070 pvl_elem i;
1071
1072 itr.kind = kind;
1073
1074 icalerror_check_arg_re( (component!=0),"component",icalcompiter_null);
1075
1076 for( i = pvl_head(impl->components); i != 0; i = pvl_next(itr.iter)) {
1077
1078 icalcomponent *c = (icalcomponent*) pvl_data(i);
1079
1080 if (icalcomponent_isa(c) == kind || kind == ICAL_ANY_COMPONENT) {
1081
1082 itr.iter = i;
1083
1084 return itr;
1085 }
1086 }
1087
1088 return icalcompiter_null;
1089}
1090
1091icalcompiter
1092icalcomponent_end_component(icalcomponent* component,icalcomponent_kind kind)
1093{
1094 struct icalcomponent_impl *impl = (struct icalcomponent_impl*)component;
1095 icalcompiter itr;
1096 pvl_elem i;
1097
1098 itr.kind = kind;
1099
1100 icalerror_check_arg_re( (component!=0),"component",icalcompiter_null);
1101
1102 for( i = pvl_tail(impl->components); i != 0; i = pvl_prior(i)) {
1103
1104 icalcomponent *c = (icalcomponent*) pvl_data(i);
1105
1106 if (icalcomponent_isa(c) == kind || kind == ICAL_ANY_COMPONENT) {
1107
1108 itr.iter = pvl_next(i);
1109
1110 return itr;
1111 }
1112 }
1113
1114 return icalcompiter_null;;
1115}
1116
1117
1118icalcomponent* icalcompiter_next(icalcompiter* i)
1119{
1120 if (i->iter == 0){
1121 return 0;
1122 }
1123
1124 icalerror_check_arg_rz( (i!=0),"i");
1125
1126 for( i->iter = pvl_next(i->iter);
1127 i->iter != 0;
1128 i->iter = pvl_next(i->iter)) {
1129
1130 icalcomponent *c = (icalcomponent*) pvl_data(i->iter);
1131
1132 if (icalcomponent_isa(c) == i->kind
1133 || i->kind == ICAL_ANY_COMPONENT) {
1134
1135 return icalcompiter_deref(i);;
1136 }
1137 }
1138
1139 return 0;
1140
1141}
1142
1143icalcomponent* icalcompiter_prior(icalcompiter* i)
1144{
1145 if (i->iter == 0){
1146 return 0;
1147 }
1148
1149 for( i->iter = pvl_prior(i->iter);
1150 i->iter != 0;
1151 i->iter = pvl_prior(i->iter)) {
1152
1153 icalcomponent *c = (icalcomponent*) pvl_data(i->iter);
1154
1155 if (icalcomponent_isa(c) == i->kind
1156 || i->kind == ICAL_ANY_COMPONENT) {
1157
1158 return icalcompiter_deref(i);;
1159 }
1160 }
1161
1162 return 0;
1163
1164}
1165icalcomponent* icalcompiter_deref(icalcompiter* i)
1166{
1167 if(i->iter ==0){
1168 return 0;
1169 }
1170
1171 return pvl_data(i->iter);
1172}
1173
1174icalcomponent* icalcomponent_get_inner(icalcomponent* comp)
1175{
1176 if (icalcomponent_isa(comp) == ICAL_VCALENDAR_COMPONENT){
1177 return icalcomponent_get_first_real_component(comp);
1178 } else {
1179 return comp;
1180 }
1181}
1182
1183
1184void icalcomponent_set_dtstart(icalcomponent* comp, struct icaltimetype v)
1185{
1186
1187 icalcomponent *inner = icalcomponent_get_inner(comp);
1188 icalproperty *prop
1189 = icalcomponent_get_first_property(inner, ICAL_DTSTART_PROPERTY);
1190
1191
1192 if (prop == 0){
1193 prop = icalproperty_new_dtstart(v);
1194 icalcomponent_add_property(inner, prop);
1195 }
1196
1197 icalproperty_set_dtstart(prop,v);
1198
1199}
1200
1201
1202struct icaltimetype icalcomponent_get_dtstart(icalcomponent* comp)
1203{
1204 icalcomponent *inner = icalcomponent_get_inner(comp);
1205 icalproperty *prop
1206 = icalcomponent_get_first_property(inner,ICAL_DTSTART_PROPERTY);
1207
1208 if (prop == 0){
1209 return icaltime_null_time();
1210 }
1211
1212 return icalproperty_get_dtstart(prop);
1213}
1214
1215
1216struct icaltimetype icalcomponent_get_dtend(icalcomponent* comp)
1217{
1218 icalcomponent *inner = icalcomponent_get_inner(comp);
1219
1220 icalproperty *end_prop
1221 = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
1222
1223 icalproperty *dur_prop
1224 = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
1225
1226
1227 if( end_prop == 0 && dur_prop == 0){
1228 return icaltime_null_time();
1229 } else if ( end_prop != 0) {
1230 return icalproperty_get_dtend(end_prop);
1231 } else if ( dur_prop != 0) {
1232
1233 struct icaltimetype start =
1234 icalcomponent_get_dtstart(inner);
1235 struct icaldurationtype duration =
1236 icalproperty_get_duration(dur_prop);
1237
1238 struct icaltimetype end = icaltime_add(start,duration);
1239
1240 return end;
1241
1242 } else {
1243 /* Error, both duration and dtend have been specified */
1244 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1245 return icaltime_null_time();
1246
1247 }
1248
1249}
1250
1251
1252void icalcomponent_set_dtend(icalcomponent* comp, struct icaltimetype v)
1253{
1254 icalcomponent *inner = icalcomponent_get_inner(comp);
1255
1256 icalproperty *end_prop
1257 = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
1258
1259 icalproperty *dur_prop
1260 = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
1261
1262
1263 if( end_prop == 0 && dur_prop == 0){
1264 end_prop = icalproperty_new_dtend(v);
1265 icalcomponent_add_property(inner,end_prop);
1266 } else if ( end_prop != 0) {
1267 icalproperty_set_dtend(end_prop,v);
1268 } else if ( dur_prop != 0) {
1269 struct icaltimetype start =
1270 icalcomponent_get_dtstart(inner);
1271
1272 struct icaltimetype end =
1273 icalcomponent_get_dtend(inner);
1274
1275 struct icaldurationtype dur
1276 = icaltime_subtract(end,start);
1277
1278 icalproperty_set_duration(dur_prop,dur);
1279
1280 } else {
1281 /* Error, both duration and dtend have been specified */
1282 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1283 }
1284}
1285
1286void icalcomponent_set_duration(icalcomponent* comp,
1287 struct icaldurationtype v)
1288{
1289 icalcomponent *inner = icalcomponent_get_inner(comp);
1290
1291 icalproperty *end_prop
1292 = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
1293
1294 icalproperty *dur_prop
1295 = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
1296
1297
1298 if( end_prop == 0 && dur_prop == 0){
1299 dur_prop = icalproperty_new_duration(v);
1300 icalcomponent_add_property(inner, dur_prop);
1301 } else if ( end_prop != 0) {
1302 struct icaltimetype start =
1303 icalcomponent_get_dtstart(inner);
1304
1305 struct icaltimetype new_end = icaltime_add(start,v);
1306
1307 icalproperty_set_dtend(end_prop,new_end);
1308
1309 } else if ( dur_prop != 0) {
1310 icalproperty_set_duration(dur_prop,v);
1311 } else {
1312 /* Error, both duration and dtend have been specified */
1313 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1314 }
1315}
1316
1317struct icaldurationtype icalcomponent_get_duration(icalcomponent* comp)
1318{
1319 icalcomponent *inner = icalcomponent_get_inner(comp);
1320
1321 icalproperty *end_prop
1322 = icalcomponent_get_first_property(inner,ICAL_DTEND_PROPERTY);
1323
1324 icalproperty *dur_prop
1325 = icalcomponent_get_first_property(inner,ICAL_DURATION_PROPERTY);
1326
1327 struct icaldurationtype null_duration;
1328 memset(&null_duration,0,sizeof(struct icaldurationtype));
1329
1330
1331 if( end_prop == 0 && dur_prop == 0){
1332 return null_duration;
1333 } else if ( end_prop != 0) {
1334 struct icaltimetype start =
1335 icalcomponent_get_dtstart(inner);
1336 time_t startt = icaltime_as_timet(start);
1337
1338 struct icaltimetype end =
1339 icalcomponent_get_dtend(inner);
1340 time_t endt = icaltime_as_timet(end);
1341
1342 return icaldurationtype_from_int(endt-startt);
1343 } else if ( dur_prop != 0) {
1344 return icalproperty_get_duration(dur_prop);
1345 } else {
1346 /* Error, both duration and dtend have been specified */
1347 icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
1348 return null_duration;
1349 }
1350}
1351
1352void icalcomponent_set_method(icalcomponent* comp, icalproperty_method method)
1353{
1354 icalproperty *prop
1355 = icalcomponent_get_first_property(comp, ICAL_METHOD_PROPERTY);
1356
1357
1358 if (prop == 0){
1359 prop = icalproperty_new_method(method);
1360 icalcomponent_add_property(comp, prop);
1361 }
1362
1363 icalproperty_set_method(prop,method);
1364
1365}
1366
1367icalproperty_method icalcomponent_get_method(icalcomponent* comp)
1368{
1369 icalproperty *prop
1370 = icalcomponent_get_first_property(comp,ICAL_METHOD_PROPERTY);
1371
1372 if (prop == 0){
1373 return ICAL_METHOD_NONE;
1374 }
1375
1376 return icalproperty_get_method(prop);
1377}
1378
1379void icalcomponent_set_dtstamp(icalcomponent* comp, struct icaltimetype v)
1380{
1381
1382 icalcomponent *inner = icalcomponent_get_inner(comp);
1383 icalproperty *prop
1384 = icalcomponent_get_first_property(inner, ICAL_DTSTAMP_PROPERTY);
1385
1386
1387 if (prop == 0){
1388 prop = icalproperty_new_dtstamp(v);
1389 icalcomponent_add_property(inner, prop);
1390 }
1391
1392 icalproperty_set_dtstamp(prop,v);
1393
1394}
1395
1396
1397struct icaltimetype icalcomponent_get_dtstamp(icalcomponent* comp)
1398{
1399 icalcomponent *inner = icalcomponent_get_inner(comp);
1400 icalproperty *prop
1401 = icalcomponent_get_first_property(inner,ICAL_DTSTAMP_PROPERTY);
1402
1403 if (prop == 0){
1404 return icaltime_null_time();
1405 }
1406
1407 return icalproperty_get_dtstamp(prop);
1408}
1409
1410
1411void icalcomponent_set_summary(icalcomponent* comp, const char* v)
1412{
1413 icalcomponent *inner = icalcomponent_get_inner(comp);
1414 icalproperty *prop
1415 = icalcomponent_get_first_property(inner, ICAL_SUMMARY_PROPERTY);
1416
1417 if (prop == 0){
1418 prop = icalproperty_new_summary(v);
1419 icalcomponent_add_property(inner, prop);
1420 }
1421
1422 icalproperty_set_summary(prop,v);
1423}
1424
1425
1426const char* icalcomponent_get_summary(icalcomponent* comp)
1427{
1428 icalcomponent *inner = icalcomponent_get_inner(comp);
1429 icalproperty *prop
1430 = icalcomponent_get_first_property(inner,ICAL_SUMMARY_PROPERTY);
1431
1432 if (prop == 0){
1433 return 0;
1434 }
1435
1436 return icalproperty_get_summary(prop);
1437
1438}
1439
1440void icalcomponent_set_comment(icalcomponent* comp, const char* v);
1441const char* icalcomponent_get_comment(icalcomponent* comp);
1442
1443void icalcomponent_set_uid(icalcomponent* comp, const char* v);
1444const char* icalcomponent_get_uid(icalcomponent* comp);
1445
1446void icalcomponent_set_recurrenceid(icalcomponent* comp,
1447 struct icaltimetype v);
1448struct icaltimetype icalcomponent_get_recurrenceid(icalcomponent* comp);
1449
1450
1451
1452
1453icalcomponent* icalcomponent_new_vcalendar()
1454{
1455 return icalcomponent_new(ICAL_VCALENDAR_COMPONENT);
1456}
1457icalcomponent* icalcomponent_new_vevent()
1458{
1459 return icalcomponent_new(ICAL_VEVENT_COMPONENT);
1460}
1461icalcomponent* icalcomponent_new_vtodo()
1462{
1463 return icalcomponent_new(ICAL_VTODO_COMPONENT);
1464}
1465icalcomponent* icalcomponent_new_vjournal()
1466{
1467 return icalcomponent_new(ICAL_VJOURNAL_COMPONENT);
1468}
1469icalcomponent* icalcomponent_new_valarm()
1470{
1471 return icalcomponent_new(ICAL_VALARM_COMPONENT);
1472}
1473icalcomponent* icalcomponent_new_vfreebusy()
1474{
1475 return icalcomponent_new(ICAL_VFREEBUSY_COMPONENT);
1476}
1477icalcomponent* icalcomponent_new_vtimezone()
1478{
1479 return icalcomponent_new(ICAL_VTIMEZONE_COMPONENT);
1480}
1481icalcomponent* icalcomponent_new_xstandard()
1482{
1483 return icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
1484}
1485icalcomponent* icalcomponent_new_xdaylight()
1486{
1487 return icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
1488}