Renamed ical_dezonify_recur() to ical_dezonify_recurse()
[citadel.git] / webcit / ical_dezonify.c
1 /* 
2  * $Id$ 
3  */
4 /**
5  * \defgroup IcalDezonify normalize ical dates to UTC
6  * Function to go through an ical component set and convert all non-UTC
7  * date/time properties to UTC.  It also strips out any VTIMEZONE
8  * subcomponents afterwards, because they're irrelevant.
9  *
10  * Everything here will work on both a fully encapsulated VCALENDAR component
11  * or any type of subcomponent.
12  *
13  * \ingroup Calendaring
14  */
15 /*@{*/
16
17 #include "webcit.h"
18 #include "webserver.h"
19
20
21 #ifdef WEBCIT_WITH_CALENDAR_SERVICE
22
23
24 /*
25  * Figure out which time zone needs to be used for timestamps that are
26  * not UTC and do not have a time zone specified.
27  *
28  * FIXME - most sites are not in New York :)
29  */
30 icaltimezone *get_default_icaltimezone(void) {
31
32         icaltimezone *zone = NULL;
33
34         if (!zone) {
35                 zone = icaltimezone_get_builtin_timezone(serv_info.serv_default_cal_zone);
36         }
37         if (!zone) {
38                 zone = icaltimezone_get_utc_timezone();
39         }
40         return zone;
41 }
42
43
44 /*
45  * Back end function for ical_dezonify()
46  *
47  * We supply this with the master component, the relevant component,
48  * and the property (which will be a DTSTART, DTEND, etc.)
49  * which we want to convert to UTC.
50  */
51 void ical_dezonify_backend(icalcomponent *cal,
52                         icalcomponent *rcal,
53                         icalproperty *prop) {
54
55         icaltimezone *t = NULL;
56         icalparameter *param;
57         const char *tzid;
58         struct icaltimetype TheTime;
59
60         /* Give me nothing and I will give you nothing in return. */
61         if (cal == NULL) return;
62
63         /* Hunt for a TZID parameter in this property. */
64         param = icalproperty_get_first_parameter(prop, ICAL_TZID_PARAMETER);
65
66         /* Get the stringish name of this TZID. */
67         if (param != NULL) {
68                 tzid = icalparameter_get_tzid(param);
69
70                 /* Convert it to an icaltimezone type. */
71                 if (tzid != NULL) {
72                         t = icalcomponent_get_timezone(cal, tzid);
73                 }
74
75         }
76
77         /* Now we know the timezone.  Convert to UTC. */
78
79         if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
80                 TheTime = icalproperty_get_dtstart(prop);
81         }
82         else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
83                 TheTime = icalproperty_get_dtend(prop);
84         }
85         else if (icalproperty_isa(prop) == ICAL_DUE_PROPERTY) {
86                 TheTime = icalproperty_get_due(prop);
87         }
88         else if (icalproperty_isa(prop) == ICAL_EXDATE_PROPERTY) {
89                 TheTime = icalproperty_get_exdate(prop);
90         }
91         else {
92                 return;
93         }
94
95         /* lprintf(9, "                * Was: %s\n", icaltime_as_ical_string(TheTime)); */
96         if (TheTime.is_utc) {
97                 /* lprintf(9, "                * This property is ALREADY UTC.\n"); */
98         }
99         else {
100                 /* Do the conversion. */
101                 if (t != NULL) {
102                         /* lprintf(9, "                * Timezone prop found.  Converting to UTC.\n"); */
103                 }
104                 else {
105                         /* lprintf(9, "                * Converting default timezone to UTC.\n"); */
106                 }
107
108                 if (t == NULL) {
109                         t = get_default_icaltimezone();
110                 }
111
112                 icaltimezone_convert_time(&TheTime,
113                                         t,
114                                         icaltimezone_get_utc_timezone()
115                 );
116                 TheTime.is_utc = 1;
117         }
118
119         icalproperty_remove_parameter_by_kind(prop, ICAL_TZID_PARAMETER);
120         /* lprintf(9, "                * Now: %s\n", icaltime_as_ical_string(TheTime)); */
121
122         /* Now add the converted property back in. */
123         if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
124                 icalproperty_set_dtstart(prop, TheTime);
125         }
126         else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
127                 icalproperty_set_dtend(prop, TheTime);
128         }
129         else if (icalproperty_isa(prop) == ICAL_DUE_PROPERTY) {
130                 icalproperty_set_due(prop, TheTime);
131         }
132         else if (icalproperty_isa(prop) == ICAL_EXDATE_PROPERTY) {
133                 icalproperty_set_exdate(prop, TheTime);
134         }
135 }
136
137
138 /*
139  * Recursive portion of ical_dezonify()
140  */
141 void ical_dezonify_recurse(icalcomponent *cal, icalcomponent *rcal) {
142         icalcomponent *c;
143         icalproperty *p;
144
145         /*
146          * Recurse through all subcomponents *except* VTIMEZONE ones.
147          */
148         for (c=icalcomponent_get_first_component(
149                                         rcal, ICAL_ANY_COMPONENT);
150                 c != NULL;
151                 c = icalcomponent_get_next_component(
152                                         rcal, ICAL_ANY_COMPONENT)
153         ) {
154                 if (icalcomponent_isa(c) != ICAL_VTIMEZONE_COMPONENT) {
155                         ical_dezonify_recurse(cal, c);
156                 }
157         }
158
159         /*
160          * Now look for DTSTART and DTEND properties
161          */
162         for (p=icalcomponent_get_first_property(
163                                 rcal, ICAL_ANY_PROPERTY);
164                 p != NULL;
165                 p = icalcomponent_get_next_property(
166                                 rcal, ICAL_ANY_PROPERTY)
167         ) {
168                 if (
169                         (icalproperty_isa(p) == ICAL_DTSTART_PROPERTY)
170                         || (icalproperty_isa(p) == ICAL_DTEND_PROPERTY)
171                         || (icalproperty_isa(p) == ICAL_DUE_PROPERTY)
172                         || (icalproperty_isa(p) == ICAL_EXDATE_PROPERTY)
173                    ) {
174                         ical_dezonify_backend(cal, rcal, p);
175                 }
176         }
177 }
178
179
180 /*
181  * Convert all DTSTART and DTEND properties in all subcomponents to UTC.
182  * This function will search any VTIMEZONE subcomponents to learn the
183  * relevant timezone information.
184  */
185 void ical_dezonify(icalcomponent *cal) {
186         icalcomponent *vt = NULL;
187
188         /* lprintf(9, "ical_dezonify() started\n"); */
189
190         /* Convert all times to UTC */
191         ical_dezonify_recurse(cal, cal);
192
193         /* Strip out VTIMEZONE subcomponents -- we don't need them anymore */
194         while (vt = icalcomponent_get_first_component(
195                         cal, ICAL_VTIMEZONE_COMPONENT), vt != NULL) {
196                 icalcomponent_remove_component(cal, vt);
197                 icalcomponent_free(vt);
198         }
199
200         /* lprintf(9, "ical_dezonify() completed\n"); */
201 }
202
203
204 #endif /* WEBCIT_WITH_CALENDAR_SERVICE */