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