* Another attempt at fixing timezones :(
[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
11 #include "sysdep.h"
12 #include <unistd.h>
13 #include <sys/types.h>
14 #include <limits.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <strings.h>
18 #include "citadel.h"
19 #include "server.h"
20 #include "citserver.h"
21 #include "sysdep_decls.h"
22 #include "support.h"
23 #include "config.h"
24
25 #ifdef HAVE_ICAL_H
26 #include <ical.h>
27 #include "ical_dezonify.h"
28
29 /*
30  * Back end function for ical_dezonify()
31  *
32  * We supply this with the master component, the relevant component,
33  * and the property (which will be a DTSTART of DTEND)
34  * which we want to convert to UTC.
35  */
36 void ical_dezonify_backend(icalcomponent *cal,
37                         icalcomponent *rcal,
38                         icalproperty *prop) {
39
40         icaltimezone *t;
41         icalparameter *param;
42         const char *tzid;
43         struct icaltimetype TheTime;
44
45         /* Give me nothing and I will give you nothing in return. */
46         if (cal == NULL) return;
47
48         /* Hunt for a TZID parameter in this property. */
49         param = icalproperty_get_first_parameter(prop, ICAL_TZID_PARAMETER);
50         if (param == NULL) return;
51
52         /* Get the stringish name of this TZID. */
53         tzid = icalparameter_get_tzid(param);
54         if (tzid == NULL) return;
55
56         /* Convert it to an icaltimezone type. */
57         t = icalcomponent_get_timezone(cal, tzid);
58         if (t == NULL) return;
59
60         /* Now we know the timezone.  Convert to UTC. */
61
62         if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
63                 TheTime = icalproperty_get_dtstart(prop);
64         }
65         else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
66                 TheTime = icalproperty_get_dtend(prop);
67         }
68         else {
69                 return;
70         }
71
72         /* Remove the property from the component. */
73         icalcomponent_remove_property(rcal, prop);
74         icalproperty_free(prop);
75
76         /* Do the conversion. */
77         icaltimezone_convert_time(&TheTime,
78                                 t,
79                                 icaltimezone_get_utc_timezone()
80         );
81
82         /* Now add the converted property back in. */
83         if (icalproperty_isa(prop) == ICAL_DTSTART_PROPERTY) {
84                 prop = icalproperty_new_dtstart(TheTime);
85                 icalcomponent_add_property(rcal, prop);
86         }
87         else if (icalproperty_isa(prop) == ICAL_DTEND_PROPERTY) {
88                 prop = icalproperty_new_dtend(TheTime);
89                 icalcomponent_add_property(rcal, prop);
90         }
91
92 }
93
94
95 /*
96  * Recursive portion of ical_dezonify()
97  */
98 void ical_dezonify_recur(icalcomponent *cal, icalcomponent *rcal) {
99         icalcomponent *c;
100         icalproperty *p;
101
102         /*
103          * Recurse through all subcomponents *except* VTIMEZONE ones.
104          */
105         for (c=icalcomponent_get_first_component(
106                                         rcal, ICAL_ANY_COMPONENT);
107                 c != NULL;
108                 c = icalcomponent_get_next_component(
109                                         rcal, ICAL_ANY_COMPONENT)
110         ) {
111                 if (icalcomponent_isa(c) != ICAL_VTIMEZONE_COMPONENT) {
112                         ical_dezonify_recur(cal, c);
113                 }
114         }
115
116         /*
117          * Now look for DTSTART and DTEND properties
118          */
119         for (p=icalcomponent_get_first_property(
120                                 rcal, ICAL_ANY_PROPERTY);
121                 p != NULL;
122                 p = icalcomponent_get_next_property(
123                                 rcal, ICAL_ANY_PROPERTY)
124         ) {
125                 if (
126                         (icalproperty_isa(p) == ICAL_DTSTART_PROPERTY)
127                         || (icalproperty_isa(p) == ICAL_DTEND_PROPERTY)
128                    ) {
129                         ical_dezonify_backend(cal, rcal, p);
130                 }
131         }
132 }
133
134
135 /*
136  * Convert all DTSTART and DTEND properties in all subcomponents to UTC.
137  * This function will search any VTIMEZONE subcomponents to learn the
138  * relevant timezone information.
139  */
140 void ical_dezonify(icalcomponent *cal) {
141         icalcomponent *vt = NULL;
142
143         /* Convert all times to UTC */
144         ical_dezonify_recur(cal, cal);
145
146         /* Strip out VTIMEZONE subcomponents -- we don't need them anymore */
147         while (vt = icalcomponent_get_first_component(
148                         cal, ICAL_VTIMEZONE_COMPONENT), vt != NULL) {
149                 icalcomponent_remove_component(cal, vt);
150                 icalcomponent_free(vt);
151         }
152
153         lprintf(9, "dezonify:\n%s\n", icalcomponent_as_ical_string(cal));
154 }
155
156 #endif /* HAVE_ICAL_H */