ical_dezonify: rearranged code and added log output
[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  * date/time properties to UTC.  It also strips out any VTIMEZONE
6  * subcomponents afterwards, because they're irrelevant.
7  *
8  */
9
10
11 #include "sysdep.h"
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <limits.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <strings.h>
19 #include "citadel.h"
20 #include "server.h"
21 #include "citserver.h"
22 #include "sysdep_decls.h"
23 #include "support.h"
24 #include "config.h"
25
26 #ifdef CITADEL_WITH_CALENDAR_SERVICE
27 #include <ical.h>
28 #include "ical_dezonify.h"
29
30
31 /*
32  * Back end function for ical_dezonify()
33  *
34  * We supply this with the master component, the relevant component,
35  * and the property (which will be a DTSTART, DTEND, etc.)
36  * which we want to convert to UTC.
37  */
38 void ical_dezonify_backend(icalcomponent *cal,
39                         icalcomponent *rcal,
40                         icalproperty *prop) {
41
42         icaltimezone *t = NULL;
43         icalparameter *param;
44         const char *tzid;
45         struct icaltimetype TheTime;
46
47         /* Give me nothing and I will give you nothing in return. */
48         if (cal == NULL) return;
49
50         /* Hunt for a TZID parameter in this property. */
51         param = icalproperty_get_first_parameter(prop, ICAL_TZID_PARAMETER);
52
53         /* Get the stringish name of this TZID. */
54         if (param != NULL) {
55                 tzid = icalparameter_get_tzid(param);
56
57                 /* Convert it to an icaltimezone type. */
58                 if (tzid != NULL) {
59                         t = icalcomponent_get_timezone(cal, tzid);
60                 }
61
62         }
63
64         /* Now we know the timezone.  Convert to UTC. */
65
66         if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
67                 TheTime = icalproperty_get_dtstart(prop);
68         }
69         else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
70                 TheTime = icalproperty_get_dtend(prop);
71         }
72         else if (icalproperty_isa(prop) == ICAL_DUE_PROPERTY) {
73                 TheTime = icalproperty_get_due(prop);
74         }
75         else if (icalproperty_isa(prop) == ICAL_EXDATE_PROPERTY) {
76                 TheTime = icalproperty_get_exdate(prop);
77         }
78         else {
79                 return;
80         }
81
82         if (TheTime.is_utc) {
83                 lprintf(CTDL_DEBUG, "                * This property is ALREADY UTC.\n");
84         }
85         else {
86                 /* Do the conversion. */
87                 if (t != NULL) {
88                         lprintf(CTDL_DEBUG, "                * Timezone prop found.  Converting to UTC.\n");
89                         icaltimezone_convert_time(&TheTime,
90                                                 t,
91                                                 icaltimezone_get_utc_timezone()
92                         );
93                         TheTime.is_utc = 1;
94                 }
95                 else {
96                         lprintf(CTDL_DEBUG, "                * Not UTC but no tzid found; WTF??\n");
97                 }
98         }
99         icalproperty_remove_parameter_by_kind(prop, ICAL_TZID_PARAMETER);
100
101         /* Now add the converted property back in. */
102         if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
103                 icalproperty_set_dtstart(prop, TheTime);
104         }
105         else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
106                 icalproperty_set_dtend(prop, TheTime);
107         }
108         else if (icalproperty_isa(prop) == ICAL_DUE_PROPERTY) {
109                 icalproperty_set_due(prop, TheTime);
110         }
111         else if (icalproperty_isa(prop) == ICAL_EXDATE_PROPERTY) {
112                 icalproperty_set_exdate(prop, TheTime);
113         }
114 }
115
116
117 /*
118  * Recursive portion of ical_dezonify()
119  */
120 void ical_dezonify_recur(icalcomponent *cal, icalcomponent *rcal) {
121         icalcomponent *c;
122         icalproperty *p;
123
124         /*
125          * Recurse through all subcomponents *except* VTIMEZONE ones.
126          */
127         for (c=icalcomponent_get_first_component(
128                                         rcal, ICAL_ANY_COMPONENT);
129                 c != NULL;
130                 c = icalcomponent_get_next_component(
131                                         rcal, ICAL_ANY_COMPONENT)
132         ) {
133                 if (icalcomponent_isa(c) != ICAL_VTIMEZONE_COMPONENT) {
134                         ical_dezonify_recur(cal, c);
135                 }
136         }
137
138         /*
139          * Now look for DTSTART and DTEND properties
140          */
141         for (p=icalcomponent_get_first_property(
142                                 rcal, ICAL_ANY_PROPERTY);
143                 p != NULL;
144                 p = icalcomponent_get_next_property(
145                                 rcal, ICAL_ANY_PROPERTY)
146         ) {
147                 if (
148                         (icalproperty_isa(p) == ICAL_DTSTART_PROPERTY)
149                         || (icalproperty_isa(p) == ICAL_DTEND_PROPERTY)
150                         || (icalproperty_isa(p) == ICAL_DUE_PROPERTY)
151                         || (icalproperty_isa(p) == ICAL_EXDATE_PROPERTY)
152                    ) {
153                         ical_dezonify_backend(cal, rcal, p);
154                 }
155         }
156 }
157
158
159 /*
160  * Convert all DTSTART and DTEND properties in all subcomponents to UTC.
161  * This function will search any VTIMEZONE subcomponents to learn the
162  * relevant timezone information.
163  */
164 void ical_dezonify(icalcomponent *cal) {
165         icalcomponent *vt = NULL;
166
167         lprintf(CTDL_DEBUG, "ical_dezonify() started\n");
168
169         /* Convert all times to UTC */
170         ical_dezonify_recur(cal, cal);
171
172         /* Strip out VTIMEZONE subcomponents -- we don't need them anymore */
173         while (vt = icalcomponent_get_first_component(
174                         cal, ICAL_VTIMEZONE_COMPONENT), vt != NULL) {
175                 icalcomponent_remove_component(cal, vt);
176                 icalcomponent_free(vt);
177         }
178
179         lprintf(CTDL_DEBUG, "ical_dezonify() completed\n");
180 }
181
182
183 #endif /* CITADEL_WITH_CALENDAR_SERVICE */