* set up ical_dezonify() to be called at appropriate times
[citadel.git] / citadel / ical_dezonify.c
1 /* 
2  * $Id$ 
3  *
4  * Function to go through an ical component set and convert all non-UTC
5  * DTSTART and DTEND properties to UTC.  It also strips out any VTIMEZONE
6  * subcomponents afterwards, because they're irrelevant.
7  *
8  */
9
10 #ifdef HAVE_ICAL_H
11
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <fcntl.h>
17 #include <sys/types.h>
18 #include <ical.h>
19 #include "ical_dezonify.h"
20
21 /*
22  * Back end function for ical_dezonify()
23  *
24  * We supply this with the master component and the property (which will
25  * be a DTSTART or DTEND) which we want to convert to UTC.
26  */
27 void ical_dezonify_backend(icalcomponent *cal, icalproperty *prop) {
28         icaltimezone *t;
29         icalparameter *param;
30         const char *tzid;
31         struct icaltimetype TheTime;
32
33         /* Give me nothing and I will give you nothing in return. */
34         if (cal == NULL) return;
35
36         /* Hunt for a TZID parameter in this property. */
37         param = icalproperty_get_first_parameter(prop, ICAL_TZID_PARAMETER);
38         if (param == NULL) {
39                 printf("No tzid parameter found - "
40                         "perhaps this component is already UTC?\n");
41                 return;
42         }
43
44         /* Get the stringish name of this TZID. */
45         tzid = icalparameter_get_tzid(param);
46         if (tzid == NULL) {
47                 printf("icalparameter_get_tzid() returned NULL\n");
48                 return;
49         }
50
51         /* Convert it to an icaltimezone type. */
52         t = icalcomponent_get_timezone(cal, tzid);
53         if (t == NULL) {
54                 printf("icalcomponent_get_timezone(%s) returned NULL\n", tzid);
55         }
56
57         /* Now we know the timezone.  Convert to UTC. */
58
59         if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
60                 TheTime = icalproperty_get_dtstart(prop);
61         }
62         else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
63                 TheTime = icalproperty_get_dtend(prop);
64         }
65
66         /* Do the conversion.
67          */
68         icaltimezone_convert_time(&TheTime,
69                                 t,
70                                 icaltimezone_get_utc_timezone()
71         );
72
73         /* Now strip the TZID parameter, because it's incorrect now. */
74         icalproperty_remove_parameter(prop, ICAL_TZID_PARAMETER);
75
76         if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
77                 icalproperty_set_dtstart(prop, TheTime);
78         }
79         else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
80                 icalproperty_set_dtend(prop, TheTime);
81         }
82
83 }
84
85
86 /*
87  * Recursive portion of ical_dezonify()
88  */
89 void ical_dezonify_recur(icalcomponent *cal, icalcomponent *rcal) {
90         icalcomponent *c;
91         icalproperty *p;
92
93         /*
94          * Recurse through all subcomponents *except* VTIMEZONE ones.
95          */
96         for (c=icalcomponent_get_first_component(
97                                         rcal, ICAL_ANY_COMPONENT);
98                 c != NULL;
99                 c = icalcomponent_get_next_component(
100                                         rcal, ICAL_ANY_COMPONENT)
101         ) {
102                 if (icalcomponent_isa(c) != ICAL_VTIMEZONE_COMPONENT) {
103                         ical_dezonify_recur(cal, c);
104                 }
105         }
106
107         /*
108          * Now look for DTSTART and DTEND properties
109          */
110         for (p=icalcomponent_get_first_property(
111                                 rcal, ICAL_ANY_PROPERTY);
112                 p != NULL;
113                 p = icalcomponent_get_next_property(
114                                 rcal, ICAL_ANY_PROPERTY)
115         ) {
116                 if (
117                         (icalproperty_isa(p) == ICAL_DTSTART_PROPERTY)
118                         || (icalproperty_isa(p) == ICAL_DTEND_PROPERTY)
119                    ) {
120                         ical_dezonify_backend(cal, p);
121                 }
122         }
123 }
124
125
126 /*
127  * Convert all DTSTART and DTEND properties in all subcomponents to UTC.
128  * This function will search any VTIMEZONE subcomponents to learn the
129  * relevant timezone information.
130  */
131 void ical_dezonify(icalcomponent *cal) {
132         icalcomponent *vt = NULL;
133
134         /* Convert all times to UTC */
135         ical_dezonify_recur(cal, cal);
136
137         /* Strip out VTIMEZONE subcomponents -- we don't need them anymore */
138         while (vt = icalcomponent_get_first_component(
139                         cal, ICAL_VTIMEZONE_COMPONENT), vt != NULL) {
140                 icalcomponent_remove_component(cal, vt);
141                 icalcomponent_free(vt);
142         }
143 }
144
145 #endif /* HAVE_ICAL_H */